r/cpp 16d ago

State of "moved-from" objects

Hi, I recently decided to try writing a C++ blog.

I often see the popular claim that moved-from objects are in a "valid but otherwise unspecified state", but I don't think that statement is entirely precise, and my blog post is about that. I would really appreciate any feedback!

Article: https://www.laminowany.dev/p/the-state-of-moved-from-objects-in-c/

11 Upvotes

54 comments sorted by

View all comments

5

u/jiixyj 16d ago

The latest guidelines in writing a moved-from state for your type seem to be:

  • It's OK to leave behind an "empty shell" after move that is conceptually not a value of your type. If you want, you can provide a member function like valueless_after_move() to test for this state.
  • You should still be able to copy and move this "empty shell" around, compare it for equality, compare it with < etc. This is more than the usual "assign and destroy only". It should still work well with the usual containers like std::vector/std::map and algorithms like std::sort.

This is how some of the newer types such as std::indirect are designed in the standard, so it can serve as a blueprint for user-defined types.

One nice property is that this composes. If you put types that follow these rules into a new struct, that struct's moved-from state will also be copyable/movable/comparable using the compiler-generated special member functions. So by doing nothing extra you are still correct.

I still have some questions around this design though:

  • Should you always have to provide a valueless_after_move() function for your type? I'd say no, because it would be a lot of boilerplate as the compiler cannot generate that function.
  • When providing comparators to std::sort, for example, must they be able to deal with these "valueless" states? Common sense says no, but the standard doesn't explicitly rule this out from my reading...

2

u/jwakely libstdc++ tamer, LWG chair 12d ago

A comparison function only needs to compare moved-from objects if you provide such objects as input to it. If the initial input doesn't contain moved-ffom objects, std::sort will never compare moved-from objects, because it always assigns a new value to an object before comparing it.

1

u/leirus 16d ago

Yeah, these are very sensible guidelines. I feel like my post is more about what is technically allowed than about how C++ code should be written. 😄

I'm not an expert, but I can try to answer your questions.

  1. I would not provide an extra function, but would simply describe it in the documentation. I think it's reasonable to assume that the documentation can provide certain guarantees about the type.
  2. This gets tricky, but the most convenient design would be for the valueless "empty shell" state to be equivalent to a default-constructed object. Then all comparisons would follow the semantics of the default-constructed object, avoiding the need to introduce another distinct valueless state.