Boost logo

Boost :

From: Kevlin Henney (kevlin_at_[hidden])
Date: 2004-02-26 09:19:01


In message <200402261346.10248.ghost_at_[hidden]>, Vladimir Prus
<ghost_at_[hidden]> writes
>
>There's no problem with compiler actually. The real code used "const
>boost::any&", and the typo is only in the email.

In which case you got advertised behaviour, just not the behaviour that
you expected :->

>Because you wrote that exlicit constructor would give more inconvenience than
>safety, and that same subjective judgement can be used in almost all cases.

Inconvenience has both a subjective element and an objective element.
One aspect of convenience in boost::any is that because it can hold any
value -- as its name suggests -- it does so, and does so as
transparently and consistently as possible. It is safe, in exactly the
way that void * isn't, but that does not mean that all accidental misuse
is prevented or preventable -- even though it is type safe, there is
still an element of placing trust in the programmer.

>The experience in my case is very simple. I had two bugs because constructor
>is not explicit. I've just made it explicit locally, recomplied and got no
>complication errors, so convenience was not hurted.

I outlined in a previous email the intended syntax for use. To break
this would be more than a little inconvenient, and certainly against the
spirit of its design. Making the constructor 'explicit' would break the
compilation of other code that is quite reasonable -- perhaps not yours,
because you are following the style I outlined as an alternative in a
previous response -- but it would still break it and for no good reason,
eg

        std::map<std::string, boost::any> table;
        ...
        table[key] = 0; // reasonable usage

Making the constructor 'explicit' will still not trap all occurrences of
the type of error you made:

        class variable
        {
        public:
                boost::any &value();
                ...
        };
        void do_something(const pair<std::string, boost::any> &);
        ...
        variable foo;
        do_something(std::make_pair(key, foo));
                // oops, should have been foo.value

Given that you cannot trap all of the errors all of the time, the
question then becomes where should the compromise be and what are the
trade-offs? I favour the current situation for a number of reasons,
including transparency of use, which I cited as a motivating
convenience, and consistency.

It is also entirely possible that you could reconsider the interfaces or
style of design that led you to arrange your interfaces as you did.
Sometimes such usage errors point to other areas of design tension.

>I'm afraid that I prefer to use number of bugs and number of characters as the
>primary metric, because they don't allow different interpretation.

I am happy to use this metric as well, but you will find that it is not
free of interpretation. However, be aware that it is not a metric of
either safety or convenience: it is a measure of bugs and the number of
characters. When and how did your bugs manifest themselves?

Kevlin

-- 
____________________________________________________________
  Kevlin Henney                   phone:  +44 117 942 2990
  mailto:kevlin_at_[hidden]     mobile: +44 7801 073 508
  http://www.curbralan.com        fax:    +44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

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