Last Wednesday evening, I gave a talk at the Northwest C++ Users' Group entitled "The Universal Reference/Overloading Collision Conundrum." The purpose of the talk was to try out the information behind a guideline from Effective C++11/14 (the book I'm currently working on). That guideline is "Avoid overloading on universal references." The video for that talk is now available.
From my perspective, the talk was a success, but that may not be apparent from the video. Things went fine for the first 12 minutes, and then...things went less fine. Bugs in the slides. Questions I didn't answer. Material I didn't have time to cover. All of which may--should--make you wonder how I define "success."
As a general rule, I like to test material in front of live audiences before I put it in my books. Presenting technical material live is perhaps the best way to get feedback on it. Not only does it offer attendees an opportunity to ask questions and make comments (direct feedback), it gives me a chance to see people's reactions (indirect feedback). Even if an audience asks no questions and makes no comments, looking into their faces tells me if they're engaged or bored and if they're following what I'm saying or are confused. Plus, the simple act of explaining something gives me a chance to see how well it flows in practice. It's quite common for me to think to myself "this just isn't working the way I'd hoped..." while I'm speaking, and places where I think that identify parts of the presentation where I need to go back and make revisions.
From the presentation at the NWC++UG (including some conversations I had with attendees afterwards), I took away two primary lessons. First, the guideline I was presenting ("Avoid overloading on universal references") is both valid and useful. That was reassuring. Second, the technical justification I give for this guideline needs a fair amount of work. In particular, I need to avoid getting side-tracked too much by the issues surrounding overloading on universal references and its interaction with compiler-generated special functions. Both lesson will help me produce a better book, and that's why I consider the talk a success.
At the same time, I was disappointed that there were bugs in my slides. I have pretty much a zero-tolerance mindset for errors in presentation materials (as well as books and articles and other forms of publication), because authors (including me) have essentially unlimited amounts of time to prepare the materials prior to making them public. (If there's insufficient time to prepare the materials properly, my feeling is that you shouldn't agree to present or publish them.) To be honest, I was also surprised that my materials had the errors that they did, because I hadn't skimped on prep time or QA work. I really thought they were ready to go. I was mistaken. In the future, I'll clearly have to find ways to do a better job.
Since giving the talk, I've corrected and revised the materials, and the corrected slide set is available here.
I hope you enjoy the talk, rocky parts notwithstanding.
Scott
Wednesday, July 24, 2013
Wednesday, July 10, 2013
C++11 Training Materials Updated--Now With C++14 Info!
For the seventh time since originally releasing them over three years ago, I've updated my annotated training materials for "The New C++". Until this update, "the new C++" referred to C++11, but with this revision, I'm including treatment of several features from draft C++14 that I believe will make it into the new new standard. As far as I know, this makes my training materials the first "book-like" publication that covers features in C++14.
In accord with my "free updates for life" policy, people who've purchased these materials are entitled to (and should recently have received notification about) the updated version.
The latest revision of the materials contains the usual mish-mash of bug-fixes and presentation improvements (the changelog, which is delivered along with the latest matereials, has details), and those alone had me planning a release this summer. But when the C++14 CD was adopted in April, I knew I had to find a way to shoehorn some C++14 material into the course. The result is 20 new pages of information, including overviews of the following C++14 features:
In accord with my "free updates for life" policy, people who've purchased these materials are entitled to (and should recently have received notification about) the updated version.
The latest revision of the materials contains the usual mish-mash of bug-fixes and presentation improvements (the changelog, which is delivered along with the latest matereials, has details), and those alone had me planning a release this summer. But when the C++14 CD was adopted in April, I knew I had to find a way to shoehorn some C++14 material into the course. The result is 20 new pages of information, including overviews of the following C++14 features:
- Polymorphic lambdas (i.e.,
auto
parameters). - Generalized lambda captures (makes "move capture" possible).
- Variadic and perfect-forwarding lambdas.
- Generalized function return type deduction (
i.e., auto
return types). - Reader/writer locks (
i.e., std::shared_mutex
andstd::shared_lock
).
There's also a page summarizing other C++14 features, along with a slew of references for people who want to read more about the new goodies in C++14.
If you haven't done so already, I hope you'll consider purchasing a copy of these materials. As always, a free sample PDF of the first ~40 pages is available here. Don't expect too much C++14 information in that sample, because the first serious treatment of C++14 features begins on slide 90. That's not me being coy. It's just how things worked out, given the flow of topics in the course.
If you haven't done so already, I hope you'll consider purchasing a copy of these materials. As always, a free sample PDF of the first ~40 pages is available here. Don't expect too much C++14 information in that sample, because the first serious treatment of C++14 features begins on slide 90. That's not me being coy. It's just how things worked out, given the flow of topics in the course.
Scott
Sunday, July 7, 2013
When decltype meets auto
C++11 has three sets of type deduction rules:
But that's for C++11, which, among the C++-obsessed, is rapidly approaching yawnworthiness. Fortunately, C++14 is on the horizon, and one of the new features sure to stifle even the strongest of yawns is the ability to declare types using
For variable declarations, this saves you the trouble of typing the initializing expression twice,
- Those used in template type deduction.
- Those used in
auto
type deduction. - Those used by
decltype
.
auto
type deduction are the same as the rules for template type deduction, except that given a braced initializer such as { 1, 2, 3, 4 }
, auto
will deduce a std::initializer
list type (in the case of { 1, 2, 3, 4 }
, it will be std::initializer_list<int>
), while template type deduction will fail. (I have no idea why type deduction for auto
and for templates is not identical. If you know, please tell me!) The rules for decltype
are more complicated, because they don't just distinguish between lvalues and rvalues, they also distinguish between id-expressions (i.e., expressions consisting only of identifiers, e.g., variable or parameter names) and non-id-expressions. For details on all these rules, consult this article by Thomas Becker, this article by me, or this article by Herb Sutter (for auto
) and this one by Andrew Koenig (for decltype
).But that's for C++11, which, among the C++-obsessed, is rapidly approaching yawnworthiness. Fortunately, C++14 is on the horizon, and one of the new features sure to stifle even the strongest of yawns is the ability to declare types using
decltype(auto)
. This feature leads to two questions, only the first of which is rhetorical:- You can declare what?
- During type deduction for
decltype(auto)
, which type deduction rules are to be followed: those forauto
or those fordecltype
? Or doesdecltype(auto)
have its own set of type deduction rules?
decltype(auto)
uses the decltype
type deduction rules. The reason is that the type deduced by auto
for an initializing expression strips the ref-qualifiers (i.e., lvalue references and rvalue references) and top-level cv-qualifiers (i.e., const
s and volatile
s) from the expression, but decltype
does not. As a result, if you want the ref- and cv-qualifier stripping behavior, you can just write auto
. If you don't, C++14 gives you the option of writing decltype(auto)
.For variable declarations, this saves you the trouble of typing the initializing expression twice,
decltype(longAndComplexInitializingExpression) var = longAndComplexInitializingExpression; // C++11 decltype(auto) var = longAndComplexInitializingExpression; // C++14For
auto
function return types (another new C++14 feature), it's even more convenient. Consider a function template, grab
, that authenticates a user and, assuming authentication doesn't throw, returns the result of indexing into some container-like object. Bearing in mind that some standard containers return lvalue references from their operator[]
operations (e.g., std::vector
, std::deque
), while others return proxy objects (e.g., std::vector<bool>
), and I believe it would be valid to define a container such that invoking operator[]
on an rvalue would yield an rvalue reference, the proper "generic" way to declare this function in C++11 would be (I think):template<typename ContainerType, typename IndexType> //C++11 auto grab(ContainerType&& container, IndexType&& index) -> decltype(std::forward<ContainerType>(container)[std::forward<IndexType>(index)]); { authenticateUser(); return std::forward<ContainerType>(container)[std::forward<IndexType>(index)]; }In C++14, I believe this can be simplified to the following, thanks to function return type deduction and
decltype(auto)
:
template<typename ContainerType, typename IndexType> // C++14 decltype(auto) grab(ContainerType&& container, IndexType&& index) { authenticateUser(); return std::forward<ContainerType>(container)[std::forward<IndexType>(index)]; }Scott