Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Template type deduction for temporary value

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
void wrapper(T& u)
{
    g(u);
}

class A {};

void g(const A& a) {}
int main()
{
    const A ca;
    wrapper(ca);
    wrapper(A()); // Error
}

Hi I have a question on why the last statement gives a compiler error.

:18:10: error: cannot bind non-const lvalue reference of type 'A&' to an rvalue of type 'A' wrapper(A());

I thought that the template type T would be deduced as const A& as the ca is also deduced as const A&. Why the type deduction fails in this case?

like image 807
Jaebum Avatar asked Dec 10 '22 07:12

Jaebum


1 Answers

I thought that the template type T would be deduced as const A& as the ca is also deduced as const A&. Why the type deduction fails in this case?

Because that's not how the deduction rules work. They strive to deduce as much of a match to the function argument type as possible. A temporary is not necessarily const, it can just bind to a const reference.

But your function template does not accept by a const reference, instead it accepts by a non-const lvalue reference. So no const is gonna spring up unless the function argument is const itself (which it isn't).

The proper solution is to use a forwarding reference (an rvalue reference to a deduced template parameter):

template <typename T>
void wrapper(T&& u)
{
    g(std::forward<T>(u));
}

Now u can bind to any object. And the types deduced will tell you the value category of the function argument, allowing you to forward that category to the function call g(...), and making sure the proper overload is picked.


By the way, in case you are curious, if you add the const directly to the temporary type, your original code will build just fine.

using CA = A const;
wrapper(CA()); // Not an error anymore

Now u ends up being a A const& and binds to the temporary just fine. But that is just a curiosity that's unlikely to be useful in practice. Use forwarding references.

like image 125
StoryTeller - Unslander Monica Avatar answered Jan 13 '23 20:01

StoryTeller - Unslander Monica