Here is an exercise from C++ Primer 5th Edition:
Exercise 16.45: Given the following template, explain what happens if we call g on a literal value such as 42. What if we call g on a variable of type int? P.690
template <typename T>
void g(T&& val)
{
std::vector<T> v;
}
int main()
{
//g(42);
int i;
g(i);
}
When calling on 42
, it compiled.
When on i
, the compiler complained a lot of errors, part of which is pasted as below.
forming pointer to reference type 'int&'
My questions are
When calling on literal value ,42
in this case, what type was deduced for T
?
when on i
, why didn't it compile? How to understand these error messages?
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:
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.