1

I'm trying to std::move an element out of a std::set and then erase it from the set:

std::set<some_type> the_set; some_type item; for (auto iter = the_set.begin(); iter != the_set.end(); iter++) { auto miter = std::make_move_iterator(iter); item = std::move(*miter); the_set.erase(iter); break; } 

The compiler doesn't like it, though (MSVC 2015):

error C2280: 'some_type &some_type::operator =(const some_type &)': attempting to reference a deleted function 

Seems like it's trying to use a copy constructor instead, which I don't want. How would I get it to use the move constructor? (I tried the move_iterator out of desperation, not sure if it's the right solution here).

1 Answer 1

4

std::set iterators are effectively const iterators (in C++11 and later). That way, you cannot possibly change them and break set's ordering.

And you cannot move from a const&&. So you cannot move out of a set.

C++17 will permit you to do so, but via a different API (PDF). Basically, you have to extract the node itself from the set, then move the object in the node, and then destroy the node (by letting it fall off the stack). I believe the code would look something like this:

for (auto iter = the_set.begin(); iter != the_set.end(); iter++) { auto node = the_set.extract(iter); item = std::move(node.value()); break; } 
Sign up to request clarification or add additional context in comments.

3 Comments

Since in my case I'm deleting right after moving, could I use const cast to accomplish the move? I know it's probably a bit hacky...
@atanamir: Probably not. The moment you move it out (and something actually mutates its contents to swap data), the set is in inconsistent state (the sort invariant is likely broken). The algorithms it would use to remove the item rely on this invariant (heck, they rely on the object being in a usable state for stuff like operator< calls, and the only guarantee you get after you've moved out of something is that it's possible to reassign or destroy it, nothing else is allowed; it might have NULL pointers that are illegal otherwise). Don't try to do this.
@atanamir: That said, looks like C++17 is introducing std::set::extract that would allow what you're trying to do (assuming I'm reading it right).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.