
Ion GaztaƱaga wrote :
I don't think move should be implemented as swap, because the resource (shared memory) is still there floating around:
Indeed, but that is the only way to really keep the strong invariant of one-way construction (which certainly is useful, since it allows optimal object performance by avoiding tests for "emptiness" and leads to safer code since operations on empty objects may not happen). Using swap however may lead to delayed resource reclamation in expressions introducing a lot of temporaries, which is the problem you're refering to (albeit you're using casting to turn named variables into temporaries, meaning the expression is their whole scope). I'm not so sure it is that big an issue however, but your opinion may differ on that subject, hence the alternative solution below. Ideally, we would want destructive move semantics (move semantics where the moved-from object is destructed when move is performed) but those are not what C++0x provides, unfortunately.
//other_shm will be in default-constructed state shm = move(other_shm)
Why must that state be the default-constructed one? It could just be an unspecified private state than can only be reached from a move, and where only the minimum required operations, such as destruction, are valid. However, that means potential overhead for those operations. And I personally still do not know what operations are required to be valid on moved-from objects, since that is badly specified, which means in the worst case you have to support all assignment and copying scenarios from/to moved-from objects. That still provides all the safety of the original not move-aware solution, but only if the user is careful about what he does to named variables he has casted to temporaries once they have been moved,; seems safe enough. There is overhead, but only less than with allowing two-phase construction, unless the rollback semantics are hard to maintain on assignment due to exception safety issues (you might also choose not to support them here and fall back to the moved state on failure). You talked of containers; but since those are dynamically-sized sequences of elements, it makes sense for them to be empty, i.e. to be a sequence of 0 element. On the other hand, for a lot of other things, being empty doesn't make much sense.