4

Here's C++17's current description of MoveAssignable:

t = rv;

If t and rv do not refer to the same object, t is equivalent to the value of rv before the assignment rv's state is unspecified. [ Note: rv must still meet the requirements of the library component that is using it, whether or not t and rv refer to the same object. The operations listed in those requirements must work as specified whether rv has been moved from or not. — end note ]

What does "rv must still meet the requirements of the library component that is using it" refer to?

What if t & rv refer to the same object? What can/should a type with MoveAssignable do in this case?

Does the description mean:

  1. the library won't call move assignment with self at all, so the type can do whatever it wants in this case (even crash)

  2. or the type should handle this case somehow (no crashing allowed), but its result doesn't matter

  3. or something else?

Note: there are similar questions here at SO, but there are conflicting/old (C++14 has different rules) answers, comments, so I'd like to clarify this.

geza
  • 28,403
  • 6
  • 61
  • 135
  • 3
    Whatever the standard currently says, what it should say is what Eric Niebler wrote here: http://ericniebler.com/2017/03/31/post-conditions-on-self-move/ Basically, self-move should leave the object in a valid-but-unspecified state. The way to reason about this is to think through how `swap` is implemented, and consider that self-swap should be allowed. IIRC, the current wording makes self-move UB because of a general rule that rvalue references must not create non-unique aliases – Kerrek SB Nov 14 '17 at 22:45
  • 1
    Related [Is `x = std::move(x)` undefined?](https://stackoverflow.com/q/31547466/1708801) – Shafik Yaghmour Nov 14 '17 at 22:56

1 Answers1

2

What does "rv must still meet the requirements of the library component that is using it" refer to?

This is a roundabout way of saying that even though rv's state is unspecified, it must be a valid state. For instance, a type which records an "I'm gone!" state and throws exceptions for subsequent re-assignments is not allowed, if assignment is one of the required-to-be-supported operations.

What if t & rv refer to the same object?

You already quoted the answer to that: "rv's state is unspecified." This is independent of whether t refers to the same object.

Does the description mean:

  1. or the type should handle this case somehow (no crashing allowed), but its result doesn't matter

Yes, this, pretty much.

Community
  • 1
  • 1
  • Thanks for the answer! I've found [this](http://eel.is/c++draft/res.on.arguments#1.3): "If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument.". So, can a standard library type be a MoveAssignable then? – geza Nov 14 '17 at 23:10
  • The only subtle and maybe strange question remained is why does "rv must still meet the requirements of the library component that is using it" mean what it means? Is there some part of the standard which makes this sentence to mean that? – geza Nov 14 '17 at 23:47
  • @geza It's a non-normative note. Its meaning can be inferred from the fact that there is nothing in the standard to suggest that valid operations on moved-from objects may produce invalid results. –  Nov 15 '17 at 00:28
  • For example, `std::sort` requires the elements in the sequence to be comparable, whether or not they are in a moved-from state. – Howard Hinnant Nov 15 '17 at 04:02
  • @HowardHinnant: You've read my mind :) That's what I did, I've checked `std::sort`'s documentation when I asked that question. However, I didn't find any extra requirements (besides Move*). It is here? http://eel.is/c++draft/sort#lib:sort or somewhere else? – geza Nov 15 '17 at 19:56
  • It is in [alg.sorting]. – Howard Hinnant Nov 15 '17 at 20:43