Move semantics replace copy semantics in situations where copying is inefficient. Copy semantics deals fully with copyable objects, including const objects.
Already,
Sorry, but the premise is flawed.
An unordered_set
doesn't actually hold const
objects. It's just not giving you write access to the contained elements. That's a property of the accessors only.
It would be possible to add an key erase(iterator)
function which just moves the element out to a temporary. I'm not sure why you'd want a key&&
there.
As for const MyClass&& ~MyClass() const
, that doesn't make sense for three reasons: dtors have neither return types nor CV classification, nor is overload resolution done for them.
So basically you're saying it should be possible to move a const
object into another const
object and destroy the original?
Sorry but I think the whole point of making it const
is to prevent this.
Otherwise it would form a loophole: you could destroy-move a const
object out of its memory location, then you destroy-move another const
object into the memory location of the first one (via placement new
).
Now the object has changed even though it was const
... so essentially const
was useless.
See comments below...
Imho you have identified a real need.
Your solution sounds a lot like what I have called destructive move semantics. This possibility is described in the original move semantics proposal. I think such a design is possible, though it is not without its problems. As far as I know, no one is working this area on the standards committee.
There are simpler ways to extract move-only types out of the associative containers that would not require language changes (aside maybe from allowing type-punning without undefined behavior).
N3645 is a library-only proposal which puts a nested node_ptr
type into each container. The node_ptr
is a lot like a unique_ptr
. It has unique ownership of a node in an associative container. But when you dereference it, you get non-const access to the value_type
in the node, instead of the node itself. extract
and insert
members are added to the associative containers allowing one to insert and remove nodes (owned by the node_ptr
) to/from the containers.
You could use this to remove a node from a container, and then move a move-only type out of the node, and let ~node_ptr()
clean up the node when you are done with it. The paper includes this example to demonstrate this functionality:
set<move_only_type> s;
s.emplace(...);
move_only_type mot = move(*s.extract(s.begin())); // extract, move, deallocate node
Note that s.extract
is noexcept
, as is ~node_ptr()
of course. If the move construction of move_only_type
is noexcept
, then this whole operation is noexcept
. Otherwise if the move construction throws, the set
is left as if the item had been erased from the set
.
At the moment, no progress is being made on N3645. It has not been voted into a working draft, and I have no confidence that it ever will be.
Update C++17
I stand corrected: The functionality I describe above was voted into C++17 with P0083R3. Thanks to Cosme for reminding me of this in the comments below.