Search code examples
c++move-semanticsrvalue-referencepass-by-rvalue-referencec++23

(c++23 implicit move) Returning the moved local storage variable as an rvalue ref with only parenthesisses?


Regarding the proposal "Simpler implicit move" (P2266R1), I'm not sure if I understand this new "move-eligible" things correctly.

Please correct these points if incorrect:
[LIVE]

  1. std::forward becomes optional for perfect forwarding the rvalue ref received
template<class T>
T&& seven(T&& x) { return std::forward<T&&>(x); }

becomes

template<class T>
T&& seven(T&& x) { return x; }
  1. std::move become optional for rvalue ref created locally
Widget&&
test_seven(Widget w) {
    Widget&& rr = seven(std::move(w));
    return std::move(rr);
}

becomes

Widget&&
test_seven(Widget w) {
    Widget&& rr = seven(std::move(w));
    return rr;
}
  1. std::move optionaly becomes parenthesis only for return an rvalue ref for things created locally.
Widget&& h3(Widget t) {
  return std::move(t);
}

becomes

Widget&& h3(Widget t) {
  return (t);
}

Note: (3) : clang trunk warns of returning a local stack address at the time I post this.


Update 2021-08-02

https://github.com/cplusplus/papers/issues/968#issuecomment-915353127

https://isocpp.org/files/papers/P1018R13.html#P2266r1

Poll outcome: ✅ consensus. However, the against votes are from implementors, and bring relevant new information. This topic needs to be re-discussed, and might fail a plenary vote.


Solution

  • All three of the points are correct. In all cases, the variable in question is an implicitly movable entity (except seven if instantiated with an lvalue) and thus is treated as an xvalue.

    The parentheses here:

    Widget&& h3(Widget t) {
      return (t);
    }
    

    don't actually do anything. They would if the function returned decltype(auto) - since then without parentheses the function would return Widget (but still move t, not copy it).