
Amusingly, "null" is listed as a synonym for "invalid" (in http://thesaurus.reference.com/browse/invalid ).
Would you look at that! :-) LOL
"Specious" is close to working, and borrowing "singular" from iterators almost fits, but I can't come up with a great name either.
Well, I've never even heard of "specious" and "singular" does not seem to reflect nil's main property -- valuelessness (oh, this one is not probably good either).
And I think the problem here is that we really don't have that much to debate about (which isn't really a problem, I suppose). The only thing we disagree about is what the default constructor should do, which is why we started debating about whether the nil UUID was "invalid", since we all (as far as I can tell) agree that a default constructor shouldn't put something in an invalid state, just not what was "invalid".
You presented something like uuid::uuid(uuid::nil) which I do not object to -- my objections are to the ambiguity of the default constructor creating a special uuid::nil. Although come to think of it I think I probably still like the static uuid::nil() better as it returns ready to go uuid that I can return as in uuid do_something() { ... return uuid::nil(); } when in your variant it'll be like uuid do_something() { ... return uuid(uuid::nil); } unless uuid(uuid::nil) is not explicit. Then, uuid do_something() { ... return uuid::nil; // Implicit construction. }
To rephrase the big problem I have with making the default constructor call a generator: to me, it feels like making shared_ptr<T>() do the same as shared_ptr<T>(new T()). Sure, you could do it.
Well, I would not do that for shared_ptr as it explicitly has been designed to behave as a pointer. But I do do that for objects that are not pointers but happen to have pointer-semantics (namely my pimpl proposal in the vault).
Sure, it saves people calling new themselves. Sure, you could then have shared_ptr<T>::null() for the null pointer.
Yes, for pimpls I do exactly that. Again, I would not do that for shared_pre as it was designed to be a smart pointer with close to raw pointer semantics.
And I think it could even be done without breaking a fairly large fraction of programs. But nobody would *ever* advocate that. It'd just be a weird thing to do.
Well, I did and proposed exactly that :-), isn't that funny? Not for shared_ptr but for pimpl-based classes (http://www.ddj.com/cpp/205918714).
But there's always the other way to resolve a disagreement over semantics: parametrization!
could be overloaded to call lexical_cast<uuid<aggregate> >, the fastest option. People could have map<string, uuid<nil_default> > if
What if there was an initialization policy? boost::uuid could be boost::uuids::uuid<no_default>, since I think there are a fairly large number of use cases that don't need one at all. lexical_cast<uuid<T> they want the "if (m[foo])" shortcut. And you could have uuid<native_generator>.
The obvious question, then, is whether that's overkill :P
The main criterion for me is if the interface takes the guess-work out of equation for the user. If every constructor clearly states what it does without ambiguity, me happy. So, with things as you spelled out above, can we see how your proposed interface looks? Best, V.