Boost logo

Boost :

From: Kevlin Henney (kevlin_at_[hidden])
Date: 2004-02-26 05:07:41


In message <200402261036.28459.ghost_at_[hidden]>, Vladimir Prus
<ghost_at_[hidden]> writes
>Kevlin Henney wrote:
>
>> >(Note that the example above avoids the issue of implicit conversion (it
>> >won't compile), because it takes the parameter by non-const reference.
>> > With the current implementation, this is a good trick to use.)
>>
>> The main point to take away from this is that this is not a problem ;->
>
>I don't understand the meaning of neither first "this", nor the second
>"this" :-(

The absence of an 'explicit' is not a problem, and is therefore not
something that needs a solution. The problem you had was with a
non-conforming compiler: it is not the job of a library to fix all the
breakages in a compiler. Sorry for not being clearer.

>> >Anyway, there have been several requests for this and thus far no strong
>> >opinions against it.
>>
>> I have yet to see a convincing reason to make it explicit. Autoboxing
>> has been a part of boost::any's design from day 1, which existed before
>> Boost -- and, indeed, the "autoboxing" terminology. Supporting such
>> conversions was intentional. There is no more reason to make the
>> converting constructor of boost::any explicit than there is to make the
>> converting constructor of std::string explicit, or the conversion from
>> int to long explicit, or the conversion from T * to void *, or indeed
>> any other widening conversion.
>
>If we go further, there's no reason for explicit ctors at all?

Of course not, please don't exaggerate. If you read my email and take
the time to study more carefully the role that conversions play in the
language you will appreciate that 'explicit' is a powerful and useful
tool that is intended to disable implicit conversions where they are
harmful and meaningless. I cannot see how you would "go further" to
reach your conclusion.

Many programmers fail to distinguish between narrowing and widening
conversions, and arrive at unnecessarily constraining guidelines as a
result. Conversions play a role in supporting the concept of
substitutability, which is a significantly broader concept than the
conventional application of LSP in OO might lead you to believe.

>I think that
>quite the contrary, unless there's very compelling reason why construction
>should be implicit, it should be explicit, since that's safer.

That may be a guideline that some C++ programmers have chosen to follow,
but it is unnecessarily strict and not really in the spirit of the
language, IMHO. That is their preference, and there is nothing in wrong
in having such a preference, but it is not a preference that
boost::any's design enforces.

Implicit conversions should only be supported where they are safe and
have a strong semantic and transparent correspondence, so where there is
some notional substitutability between of source type wrt the target
type, eg int to long, derived pointer to base pointer, any value to
boost::any. A stricter guideline does not buy you any more real safety
and it is inconvenient for the common case, so I cannot see why it would
be a reasonable design goal.

So, by and large, single-argument constructors should be 'explicit': for
entity types, function object types, exception types, etc this is pretty
much a rule; for value types it is a consideration or recommendation,
but not a blanket rule.

>How is this going to make things safer? I my case I was passing expression of
>type boost::any to function which took boost::any. Refactoring changed the
>type, and code suddenly broke. I'm not sure the above would have helped.

You were using a broken compiler: that was the root cause of the
problem.

>For a better mix of safely and convenience, it's possible to introduce 'reset'
>method:
>
> boost::any bar(1);
> bar.reset(2);

Ugh. No. That again misses the point and transparency of value-based
programming. C++ is a language that has good support for value-based
programming. It can support meaningful conversions and restrict
meaningless ones, at the discretion of the programmer. If you want Ada,
you can Google for it ;->

>> The important point is that implicit conversions from boost::any should
>> not be allowed, and they never have been.
>
>And that's another question. Conversions *from* boost::any are quite verbose.
>So why try to make boost::any initialisation concise, if further usage is
>still verbose?

Again, if you study the nature and role of conversions in more detail
you will see that your conclusion does not follow. Not all kinds of
conversion have the same weight and consequences, and they should be
treated accordingly: narrowing conversions are potentially dangerous,
and need to be marked in code; widening conversions are not, and do not.

HTH

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