#include <iostream>
class A
{
public:
A() {};
};
template <class T>
class Test
{
public:
void func1(T&& t)
{
}
};
int main()
{
A a;
Test<A> o1;
o1.func1(a);
return 0;
}
Following errors are seen on compilation
error C2664: 'void Test<A>::func1(T &&)': cannot convert argument 1 from 'A' to 'T &&'
note: You cannot bind an lvalue to an rvalue reference
o1
is obtained by instantiating template class Test with "A"
. So the call o1.func1(a)
should know that void func1(T&& t)
should resolve to void func1(A&& t)
I thought T&&
in void func1(T&& t)
should be deduced as a universal reference or a forwarding reference because its from a template type parameter. Then why in the error above it says "You cannot bind an lvalue to an rvalue reference"
?
Am i missing some template magic here?
I thought
T&&
invoid func1(T&& t)
should be deduced as a universal reference or a forwarding reference [...]
No. t
in your example is not a universal reference. To be a universal reference it must be deduced from the call, but in your example T
is just A
. This is a universal reference:
template <class T>
class Test
{
public:
template <typename X>
void func1(X&& t)
{
}
};
The important detail is "deduced". In your example nothing is being deduced. Consider that Test<A>
is equivalent to
class TestA
{
public:
void func1(A&& t)
{
}
};
Once you instantiated the class template, its method func1
has argument of tpye A&&
, not something else, ie there is nothing to be deduced anymore. Template argument deduction takes place when you do not explicitly state the template argument, as in
template <typename T> void foo(T&& t) {};
foo(1);