Question about slide 71, int && h() { int x = 42; return x;} is it not true that this is OK according to reference lifetime extension? (although ok maybe pathological code), what do you think about reference lifetime extension? Is there a reason for it to exist if move semantics are done properly?
37:50 what is decltype(auto)? Why can't you just use auto here? I would expect "decltype(t.foo()) x = t.foo();" or "auto x = t.foo();" What is the reason for "decltype(auto)" and what does it mean?
`decltype(auto)` means "the undecayed type of the right-hand side," whereas `auto` alone means "the decayed type of the right-hand side." So on slide 42, `auto x = B().foo()` would be like `B x = B().foo()`, but `decltype(auto) x = B().foo()` would be like `B& x = B().foo()`. `decltype(auto)` means the same thing as `decltype(t.foo())` in this case. The more common use of `decltype(auto)` is as a return type. For example, `template decltype(auto) firstelt(T&& t) { return std::get(std::forward(t)); }` means [almost] the same thing as `template auto firstelt(T&& t) -> decltype(std::get(std::forward(t))) { return std::get(std::forward(t)); }` but is a lot less typing. ["Almost": the difference is that the latter is SFINAE-friendly.]
Yes, all else being equal, this is a place NRVO could kick in. But there's a trick with NRVO, implied by its formal name "copy elision." When NRVO happens, we're not saying there's *no* copy! We're saying that semantically there *is* a copy; it's just that the compiler is allowed to optimize by eliding it. We're still eliding some *thing*, and the compiler still has to figure out what that thing is. In general, if class X's copy constructor is =delete'd, then you're not allowed to return X objects by copy - not even if the copy would go on to be elided. And on slide 72, since struct auto_ptr has no constructor from an xvalue auto_ptr, then you're not allowed to return x (as a move-eligible id-expression) by move - not even if the move would go on to be elided. Very bad analogy: It's kind of like, you're trying to buy a copy operation, and NRVO gives you a coupon for "100% off" the *price* of a copy operation; but if there are no suitable copy operations "in stock" at the copy store, then merely having the coupon doesn't help.
The conclusion about the Ambig case is incorrect. In [over.match.general], "If a best viable function exists and is unique, overload resolution succeeds and produces it as the result. Otherwise overload resolution fails...". Ambiguity is a failure of overload resolution, so the second round kicks in and succeeds, making the program well-formed. The behavior of GCC, Clang and MSVC is conformant.
@49:27 - I don't think I really make any "conclusion" about this example, let alone an "incorrect" conclusion; I merely say that I understand how the wording circa May 2021 was easy for vendors to disagree about. In this video I don't think I even bothered to name the Big Four vendor who disagreed - but in P2266 ( www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2266r3.html#two-resolutions ) I did: it was EDG. :) Happily, since P2266 was adopted for C++23 ( github.com/cplusplus/draft/commit/d696d9482c0c738a8131ee0089ed7e4484240240 ), the whole example is obsolete. As of September 2023, the only Big Four vendor who's non-conforming on this example is MSVC ( godbolt.org/z/ha9o97cK8 ).
Arthur is one of my favorite speakers on C++. Not only are they informative they are engaging and entertaining.
Really good compele guide to a NRVO, rvalues and much more. No fillers, just packing with technical stuff. Great talk.
Very interesting thank you for putting this together
Glad you enjoyed it
the x64 calling convention is that the first 6 or so parameters are passed through registers. on x86 everything goes through the stack.
42:40 I believe the warnings an -Wpessimizing-move and -Wredundant-move, but as Arthur said, C++20 just deals with this directly.
Question about slide 71, int && h() { int x = 42; return x;} is it not true that this is OK according to reference lifetime extension? (although ok maybe pathological code), what do you think about reference lifetime extension? Is there a reason for it to exist if move semantics are done properly?
37:50 what is decltype(auto)? Why can't you just use auto here? I would expect "decltype(t.foo()) x = t.foo();" or "auto x = t.foo();" What is the reason for "decltype(auto)" and what does it mean?
`decltype(auto)` means "the undecayed type of the right-hand side," whereas `auto` alone means "the decayed type of the right-hand side." So on slide 42, `auto x = B().foo()` would be like `B x = B().foo()`, but `decltype(auto) x = B().foo()` would be like `B& x = B().foo()`. `decltype(auto)` means the same thing as `decltype(t.foo())` in this case.
The more common use of `decltype(auto)` is as a return type. For example, `template decltype(auto) firstelt(T&& t) { return std::get(std::forward(t)); }` means [almost] the same thing as `template auto firstelt(T&& t) -> decltype(std::get(std::forward(t))) { return std::get(std::forward(t)); }` but is a lot less typing. ["Almost": the difference is that the latter is SFINAE-friendly.]
Add a move constructor to auto_ptr? Why? It has been removed from the standard in C++17 already...
Slide 72:
Why this should not compile? Isn't RVO kick in here?
Yes, all else being equal, this is a place NRVO could kick in. But there's a trick with NRVO, implied by its formal name "copy elision." When NRVO happens, we're not saying there's *no* copy! We're saying that semantically there *is* a copy; it's just that the compiler is allowed to optimize by eliding it. We're still eliding some *thing*, and the compiler still has to figure out what that thing is. In general, if class X's copy constructor is =delete'd, then you're not allowed to return X objects by copy - not even if the copy would go on to be elided. And on slide 72, since struct auto_ptr has no constructor from an xvalue auto_ptr, then you're not allowed to return x (as a move-eligible id-expression) by move - not even if the move would go on to be elided.
Very bad analogy: It's kind of like, you're trying to buy a copy operation, and NRVO gives you a coupon for "100% off" the *price* of a copy operation; but if there are no suitable copy operations "in stock" at the copy store, then merely having the coupon doesn't help.
The conclusion about the Ambig case is incorrect. In [over.match.general], "If a best viable function exists and is unique, overload resolution succeeds and produces it as the result. Otherwise overload resolution fails...". Ambiguity is a failure of overload resolution, so the second round kicks in and succeeds, making the program well-formed. The behavior of GCC, Clang and MSVC is conformant.
@49:27 - I don't think I really make any "conclusion" about this example, let alone an "incorrect" conclusion; I merely say that I understand how the wording circa May 2021 was easy for vendors to disagree about. In this video I don't think I even bothered to name the Big Four vendor who disagreed - but in P2266 ( www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2266r3.html#two-resolutions ) I did: it was EDG. :) Happily, since P2266 was adopted for C++23 ( github.com/cplusplus/draft/commit/d696d9482c0c738a8131ee0089ed7e4484240240 ), the whole example is obsolete. As of September 2023, the only Big Four vendor who's non-conforming on this example is MSVC ( godbolt.org/z/ha9o97cK8 ).