Friday, November 2, 2012

"Universal References in C++11" now online at ISOCpp.org

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

4 comments:

Fran├žois-Xavier Bourlet said...

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!

Anubhav said...

Firstly, thanks for such a nice article. I had to read a few sections of the standard more than once to correlate with the concepts.

In 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 &.

Scott Meyers said...

@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."

In 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.

Anubhav said...

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.

Yes, it is clear now. Thanks Scott!.