Subject: Re: [boost] [uuid] Interface
From: Vladimir Batov (batov_at_[hidden])
Date: 2008-12-23 15:02:57


Dave,

> However, for move semantics (and what could be more suited to that than
> a UUID?) the invariant often needs to include a "empty" moved-from state
> anyway, and you could argue that one might as well implement a cheap,
> non-throwing default ctor that produces that state. The argument I
> sometimes use against it is that even though the empty state technically
> becomes part of the class invariant, limiting that state to moved-from
> objects still offers some improved ability to reason about code... but
> that's a weaker argument than I'd like.

I just read "n2027: A Brief Introduction to Rvalue References" (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html) and there the move is done manually:

    // move semantics
    clone_ptr(clone_ptr&& p)
        : ptr(p.ptr) {p.ptr = 0;}

That is, we manually take a resource (ptr) from the source (p), assign the resource to the target (this) and re-assign the target resource (p.ptr = 0). Therefore, I am glad to see that there seems *no* requirement to provide some special "empty" state and hijack the default constructor for the purpose -- it's up to the implementer to decide which state satisfy the need. Taking the discussed uuid as an example that might look like the following:

    uuid(uuid&& p)
        : data_(p.data_) { p = uuid::nil(); }

or

    uuid(uuid&& p)
    { *this = uuid::nil(); std::swap(*this, p); }

So, we seem to be safe and sound with the uuid default constructor (or lack of it) unaffected and irrelevant. Does it make sense?

Best,
V.