Search code examples
c++templatesrvalue-reference

Templated rvalue reference vs non templated compilation errors


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

template<typename T> void f1(T&& a) {}

void f2(int&& a) {}

int main()
{
  int i = 0;
  f1(i);//This is fine
  f2(i);//This gives compilation error

}

Why is same type of calling is having different compilation rules?

templated f1 accepts lvalue, but non templated function doesn't accept lvalue. Why? Doesn't template instantiation of f1 for int looks like f2?

I can fix compilation issues with std::move. But above one not understood.

test.cpp: In function 'int main()': test.cpp:13:7: error: cannot bind 'int' lvalue to 'int&&' f2(i);

test.cpp:7:6: note: initializing argument 1 of 'void f2(int&&)' void f2(int&& a) {}


Solution

  • In a template context, T&& isn't just an rvalue reference, it's a forwarding reference.

    In a call f1(i), T is deduced as int&, and according to reference collapsing rules, int& && becomes int&, i.e. an lvalue reference.

    That's why it is able to bind to int x.

    In a non-template context as in f2, int&& is just an rvalue reference, with no extra magic. It will bind to rvalues only.