#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) {}
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.