From http://thbecker.net/articles/rvalue_references/section_08.html
The first of the remaining two rules for rvalue references affects old-style lvalue references as well. Recall that in pre-11 C++, it was not allowed to take a reference to a reference: something like A& & would cause a compile error. C++11, by contrast, introduces the following reference collapsing rules:
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&
Secondly, there is a special template argument deduction rule for function templates that take an argument by rvalue reference to a template argument:
template<typename T>
void foo(T&&);
Here, the following apply:
- When foo is called on an lvalue of type A, then T resolves to A& and hence, by the reference collapsing rules above, the argument type effectively becomes A&.
- When foo is called on an rvalue of type A, then T resolves to A, and hence the argument type becomes A&&.
So case 1, when passing 42, you are calling g with a rvalue, so T is resolved to int
thus g's parameter is int&&
and std::vector is legal.
In case 2, when passing i, you are calling g with a lvalue, so T is resolved to int&
thus g's parameter is int&
and std::vector<int&>
is NOT legal.
Remove the line with the vector and it will work fine in both cases.