Home > Back-end >  Why is Universal reference being treated as R-Value reference?
Why is Universal reference being treated as R-Value reference?

Time:01-13

#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?

CodePudding user response:

I thought T&& in void 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); 
  •  Tags:  
  • Related