The October
Overload article
I blogged about earlier, "Universal References in C++11," is now
available online at the spanking new
ISOCpp.org website. In conjunction with my
video presentation at Channel 9 on the same topic, this means you now have your choice of three different ways to experience my pitch for adding "universal reference" to the accepted C++ vocabulary:
- Overload version: Monochrome PDF and, if you're a subscriber, hardcopy.
- Channel 9 version: Video of me presenting the information, along with the original presentation materials.
- ISOCpp.org version: HTML version with syntax-colored code examples and live hyperlinks.
I really think that the idea of universal references helps make C++11's new "
&&
" syntax a lot easier to understand. If you agree, please use this term and encourage others to do it, too.
Scott
I definitively like and share your concept of universal reference. It really helps practically. After watching your talk, I went back on all my code make use of && and found a lots of subtle errors, not only thanks to the notion of universal reference, but also because you describe how the reference collapsing rules work in C++<=11 with precision. Thanks a lots Scott!
ReplyDeleteFirstly, thanks for such a nice article. I had to read a few sections of the standard more than once to correlate with the concepts.
ReplyDeleteIn the section titled 'Nitty Gritty Details', I don't think I have understood the paragraph 'For example, given the type for both r1 and r2 is considered to be int in a call to the template f.'. Will appreciate if you could clarify this a bit more.
Also, in the very next paragraph, I have understood it in the following way. Is it correct?
r1 and r2 are both lvalue expresions. The function template under consideration are
// for f(r1)
template void f(T &&t)
and
// for f(r2)
template void f(T &)
respectively
For the case of r1, therefore, 14.8.2.1 / 3 applies "If P is an rvalue reference to a cvunqualified template parameter and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction."
Therefore T is int &, and the deduced A is int & &&, which is nothing but int & due to reference collapsing.
For the case of r2, 14.8.2.1/3 applies - "If P is a reference type, the type referred to by P is used for type deduction."
Therefore T is deduced as int, and the deduced A is int &.
@Anubhav: When references such as r1 and r2 are passed as function arguments, the first thing that happens is that they're stripped of their referenceness. This is per 5/5: "If an expression initially has the type “reference to T” (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis."
ReplyDeleteIn the calls to f, both r1 and r2 are treated the same way. Their types are first converted to int (per 5/5 above). Then 14.8.2.1/3 kicks in for f. f's parameter type is "is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue," so both r1 and r2 lead to a deduced type of int& for the template parameter T. From there, it's just reference-collapsing. So both f(r1) and f(r2) invoke f<int&>(int&).
At least that's my understanding.
Ah Ok. I see your point now. So, the function template under consideration is the one that takes a universal reference and not the two function templates that I listed in my comment.
ReplyDeleteYes, it is clear now. Thanks Scott!.