0

Can I insert to the moved container like this:

std::unordered_set<int> foo, bar;
bar = std::move(foo);
foo.clear(); // Should I do this?
foo.insert(0);
FrozenHeart
  • 19,844
  • 33
  • 126
  • 242

2 Answers2

4

A moved-from object should no longer be used.

If you insist, you will find that clear() will actually leave you with an empty container, whether it was previously empty or not (which is not defined by the standard). Then when you insert, foo will have one element in it.

A more normal way to write code like yours would be:

bar.swap(foo);
foo.clear();
foo.insert(0);

What can I do with a moved-from object?

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • @FrozenHeart: Can you complete your sentence please? – John Zwinck Jul 18 '17 at 04:00
  • Can I use a moved-from container after the `clear` call? – FrozenHeart Jul 18 '17 at 04:00
  • I have explained how you can, but that you should not. Code as in your question should be rejected by a competent reviewer. The version in my answer using `swap()` works and is not surprising. If you insert *without* clear(), that would be even worse. – John Zwinck Jul 18 '17 at 04:01
  • I don't see any advantage of swap over move assignment. – MikeMB Jul 18 '17 at 06:02
  • 1
    @MikeMB `swap` is explicit and obvious, `move` is obscure and unclear. – K. Kirsz Jul 18 '17 at 06:59
  • @K.Kirsz: How is that? Can you elaborate a bit? – MikeMB Jul 18 '17 at 07:03
  • 1
    @MikeMB As this question (and answers) prove - it is not clear how the `move` works - not only devs don't know it, but even the spec apparently say the result is unspecified. On the other hand `swap` is well defined and obvious to anyone reading the code, be it expert or novice. – K. Kirsz Jul 18 '17 at 07:06
  • @K.Kirsz how is swap clearer then move? Both move operations and swap are defined for the user-type `bar` by the user. As far as I understand, implementing member `swap` was a common way before C++11 because `std::swap` was creating copies. After C++11 you can imho live fine without swap, only having move ctor/operator= and using `std::swap`. – Sergey.quixoticaxis.Ivanov Jul 18 '17 at 10:41
  • Also as @MikeMB mentioned in his answer, map is in _valid but unspecified_ state after the move, which is enough to ensure that pre-conditions of `clear` do hold. – Sergey.quixoticaxis.Ivanov Jul 18 '17 at 10:43
  • @K.Kirz:So if someone would post a question about std::vector::push_back it would prove that it is not clear how it works and we shouldn't use it? In any case, I don't think swap is actually any clearer than move, because move states the intent much more clearly: I can only think of a handful occasions where you actually want to swap two elements. Most of the time you just care about moving the content in one direction, which is exactly what move does. – MikeMB Jul 19 '17 at 06:10
3

First of all, you can always insert into a set. Be it moved from, cleared, filled with elements etc., because insert has no preconditions (different from than e.g. erase).

But: If you don't call clear after the move, you don't know if the newly inserted element will be the only element in the set, because after the move, foo is in a valid but unspecified state. So, not only can you call clear after the move and befor inserting new elements, in most situations you should (unless you don't care what other elements are in the set).

MikeMB
  • 20,029
  • 9
  • 57
  • 102