So when I see "Don't let T&& fool you here - T is not an rvalue reference" -- yes it fricking is! And if you're going to work on a low enough type-level that you need perfect forwarding, you NEED TO KNOW THAT.
So when I see "Don't let T&& fool you here - T is not an rvalue reference" -- yes it fricking is! And if you're going to work on a low enough type-level that you need perfect forwarding, you NEED TO KNOW THAT.
T&& is only an rvalue reference when T is a non-lvalue-reference type. If T = U& then T&& = U& because of the reference collapsing rules. If you're saying that you should understand how type deduction works and interacts with reference collapsing if you're going to write C++11 then I agree. Like much of C++, perfect forwarding's design is an ugly mess and is not amenable to a superficial understanding unless you like shooting yourself in the foot.
I don't think that's true. rvalue references can only bind to rvalues.
Here's a complete program. foo(i) won't compile bacause i is not an rvalue. bar(i) will compile, and foo(1) will compile.
#include <iostream>
using namespace std;
int foo(int&& i){ return i; }
template<class T> T bar(T&& i){ return i; }
int main() { int i=0; cout << foo(i) << endl;
return 0;
}edit: I am replying humbly. C++ is a complex language and I might very well be wrong.
Your code example does not work because you call "foo" instead of "bar". But consider this one:
#include <iostream>
using namespace std;
template<class T> T bar(T&& i){ return std::forward<T>(i); }
int main() {
int i=0;
cout << bar<int&&>(6) << endl;
return 0;
}In your example, replace bar<int&&>(6) to bar<int&&>(i).
It won't compile because i is not an r value. bar(i) will compile, because the template parameter is a universal reverence that will become an lvalue (not an rvalue) through reference collapsing.