
Mathias Gaunard wrote:
On 08/22/2011 12:53 AM, Julian Gonggrijp wrote:
Mathias Gaunard wrote:
On 08/21/2011 09:23 PM, Julian Gonggrijp wrote:
However, as Vicente Botet (and Alexander Stepanov) pointed out, there are still valid use cases for the bitwise move_raw mechanism.
Care to point out one that wouldn't be better handled by move constructors?
Any case where the object to move a value into has already been constructed?
Well, there is also move assignment.
... which differs from move_raw only in the sense that move assignment guarantees that the source is left in a valid state while move_raw does not. The latter has an obvious potential for being more efficient. Note that move_raw is not inherently required to operate in a bitwise fashion; the bitwise approach is only a default solution to make raw moves available to types which don't define their own raw move.
The layout of non-PODs is completely implementation-defined. Therefore there couldn't be anything meaningful for "underlying type". All it could be is a sequence of bytes of a certain size with a certain alignment.
The layout may be implementation-dependent but the semantics is not. Since underlying types are defined by their semantics and not by their implementation, I don't see how any implementation issue could affect their existential status.
Data has layout, code has semantics. What you call the "underlying type" is just data, so I don't see how it could have any semantics.
Maybe you mean a POD type that's allowed to alias the original type? The closest thing to this is a union that contains both the POD and the original type, which is possible in C++0x.
The underlying type is the solution to the fact that move_raw does not guarantee the source to be left in a valid state. Because of that it is defined to be a POD type which can store the state of its overlying type. As such, it is not "just data"; it has a very clear, semantic relation with its overlying type. Again, my proposal is just a default solution to fill in for types which don't specify their own underlying type. Perhaps some formal language can illustrate the semantics of move_raw and the underlying type: (semantics of copy assignment, quoted from Alexander Stepanov) assert(b == c); a = b; assert(a == b && b == c) (weaker semantics of move assignment, adapted from Alexander Stepanov) assert(b == c && &b != &c); move(b, a); assert(a == c); assert(valid(b)); (still weaker semantics of move_raw, adapted from Alexander Stepanov) assert(b == c && &b != &c); move(b, a); assert(a == c); UNDERLYING_TYPE(T) is a POD type such that the following code is valid: move_raw(a, u); move_raw(u, a); (where a, b, c are instances of some copyable or moveable type and u is an instance of the underlying type of a.)