Boost logo

Boost :

Subject: Re: [boost] [Review] UUID library (mini-)review starts today, November 23rd
From: Vladimir.Batov_at_[hidden]
Date: 2008-12-02 18:15:56


> ...
> 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.

> ...
> 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.

> ...
> 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.

> 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 UUUID 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.
:-)

Thanks,
Vladimir.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk