4 ms·
Not a bad article, but I'm so sick of the term "universal references". Perhaps useful for explaining things to the uninitiate, but a more technical understandin
by splinterofchaos 12y ago
Not a bad article, but I'm so sick of the term "universal references". Perhaps useful for explaining things to the uninitiate, but a more technical understanding requires the knowledge that rvalue references can be made from any l- or rvalue.
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.
- monk_the_dog 12y ago| but a more technical understanding requires the knowledge that rvalue references can bind to any l- or rvalue 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.
- splinterofchaos 12y agoI did not mean "any rvalue-reference" and bind to "any l- or rvalue", but that you can have an "int &&", "int& &&", "const int& &&", and even "int&& &&". I updated my comment to say "can be made from" instead "can bind to". 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; }
- monk_the_dog 12y agoMaybe you're confusing reference collapsing with universal references? 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.
- splinterofchaos 12y agoI called "bar" with "<int&&>" to demonstrate that you can bind an rvalue-ref to an rvalue-ref, not to suggest that's how it should be called.
- wmkn 12y agoAt C++Now 2014 there was some agreement on renaming 'universal references' to 'forwarding references'. Apparently, Scott Meyers, the guy that came up with the term universal references, even agreed to update his upcoming book with the new term.
- splinterofchaos 12y agoAt least "forwarding" specifies "for use in perfect forwarding", but it must be made clear that this term refers to the syntactic phenomena and they are not distinct from rvalue references.
- psykotic 12y ago> So when I see "Don't let T&& fool you here - T is not an rvalue reference" -- yes it fricking is! 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.
- eliben 12y agoThis is exactly what the linked article says about universal references, by the way. Did you actually read it, or just got angry at the title?