Subject: Re: [boost] [Review] UUID library (mini-)review starts today, November 23rd
From: Andy Tompkins (atompkins_at_[hidden])
Date: 2008-12-06 15:48:09
On Wed, 3 Dec 2008 09:15:56 +1000, Vladimir.Batov_at_[hidden] said:
> > ... Hmm, I looked at some other value types in boost and this is
> > what I found.
> > boost::gregorian::date() creates an 'not_a_date_time'. One can
> > exclude this constructor with a #define. boost::posix_time::ptime()
> > is the same as above boost::function() is initialized as empty
> > std::string() is initialized as empty boost::numeric::interval() the
> > created interval is the singleton zero boost::quaternion()
> > initialized each component/member to the default values for their
> > type (i.e. zero for floating numbers) boost::optional() is
> > uninitialized boost::rational() is 'zero'
> Some usages are legitimate (like an empty std::string is still a
> string and boost::rational() default initialization to 0). Some
> usages are IMHO mildly confusing (like boost::function()) as there is
> a clear understanding that it has to have some function, i.e. no-
> function is clearly invalid. Some others are IMHO unfortunate and
> quite confusing -- does
> boost::gregorian::date() mean 'not_a_date_time' or
> boost::gregorian::date() means 'now'?
> My view is that the interface needs to be intuitive. With the date I
> would not probably use the default constructor at all as it is not
> immediately clear what it does. Instead I'd have
> boost::date::invalid() and boost::date::now(). Deploying the default
> constructor for something apart from default construction is a hack
> unfortunately abused quite often. It does not make it right though.
> > ... And, what should the default constructor do? Create a null uuid
> > or a unique one?
> It feels like you are struggling to associate the default constructor
> with something. :-) You know, you really do not have to. The default
> constructor has quite a clear meaning. If a class has no functionality
> matching that meaning, that class should not be defining the default
> constructor and should not be hijacking that constructor for anything
> else. Convenient? Sure. Good API? Hmm, I am not sure -- a good
> interface should be saying what it means.
I also wonder about this usefulness of the default constructor for
boost::uuids::uuid. Maybe it should just be left out.
> > ... This is what I want to prevent as well. I'm concerned about the
> > user who does: boost::uuid u; // this create a unique uuid and does
> > not realize that they just ran a computational intensive function
> > when they didn't need or want to.
> I am not sure what there is not to realize? The language is clear that
> "boost::uuid u" calls the default constructor... whatever that
> constructor does (intensive or not). Treating object creation as it
> were built-in types (i.e. created uninitialized/invalid) is wrong,
> encourages the wrong programming practice and expectations and should
> not be encouraged.
I understand when a default constructor is called. I am not sure
everyone will expect the same thing from the default constructor for
boost::uuids::uuid (null or unique).
> > ... Fair. These people are likely either doing:
> > boost::uuid u = get_uuid_from_somewhere(); // eg from database
> > or
> > boost::uuid u; get_uuid_from_somewhere(u); // eg from database
> > The second case would create a unique uuid unless they remembered to
> > do: boost::uuid u(boost::uuid::null());
> There is a big difference between #1 and #2 and the language is
> lucidly clear what the difference is -- #1 does just one step and
> creates and object from another object; #2 does 2 steps -- creates an
> object with the default constructor and then applies operator=().
> Painting over that difference and encouraging user's ignorance of that
> important subtlety (for a novice) won't do anyone any good.
My point was that in both #1 and #2 the user didn't want to generate a
> > It sounds very easy for one to forget. This doesn't change
> > symentics, it is just less efficient.
> It *does* change semantics and it does change execution flow and the
> language cannot be any clearer on that. If you mean #1, then instead
> of making #2 to behave like #1, I'd prohibit #2 altogether by not
> providing the default constructor. Having said that to *me*
> "boost::uuid id;" makes sense as I read it as the language describes
> -- I create a UUID with the default constructor. My interpretation of
> it is that I trust the implementer to do the right thing for me --
> the user. I'd say, if that interpretation is subtle and really
> controversial, just get rid of the default constructor altogether.
> In the end, it's just my view. I am not prepared to die fighting
> for it. :-)
Nor am I.
> Thanks, Vladimir.
Regards, Andy Tompkins
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk