Boost logo

Boost :

From: Gennadiy E. Rozental (rogeeff_at_[hidden])
Date: 2001-09-04 13:21:34


--- In boost_at_y..., "Fernando Cacciola" <fcacciola_at_g...> wrote:
>
> ----- Original Message -----
> From: Gennadiy E. Rozental <rogeeff_at_m...>
> To: <boost_at_y...>
> Sent: Monday, September 03, 2001 10:45 PM
> Subject: [boost] Re: Proposal: statefull objects
>
>
> > > > Hi, Fernando
> > > >
> > > > >
> > > > > Hi Gennadity,
> > > > >
> > > > > > Hi, Fernando
> > > > > >
> > > > > [SNIP]
> >
> > If optional is implemented using pointers because type T does not
> > have default constructor, I do not see a reason to use it at all.
I
> > would rather use plain pointer, where NULL would meen absent
value.
> > While for build-in types default constructor exist. If user-
defined
> > class T has a default constructor it is also worth while using
> > optional<T> (value implemented) instead T*. You pay with default
> > constructor call. You buy value access efficiency.
> >
> Actually, the point is not if T provides or not a default
constructor. The
> point is that you may want to bypass it because it might be too
expensive.
> Typically, you would use a true pointer in this situation, as you
expressed,
> but that involes an extra allocation/deallocation which is even
worse than
> the extra dereferencing:
>
> Consider:
>
> class font : windows::LOGFONT
> {
> font() ; // initialize with sensible defaults.
> } ;
>
> Now, suppose you need an array of font records, but you don't want
to
> initialze every element since you will assign each element with a
sensible
> value later.
> You have 3 choices:
>
> 1) vector<font> v(1000);
> This calls 1000 unnecesary default constructors.
>
> 2) vector< shared_ptr<font> > v(1000)
> You will have to call allocation/deallocation for each elemement
later.
>
> 3) vector< optional<font> > v(1000)
> Here, you skip the 1000 ctor calls and the
allocation/deallocation
> altogether.

The difference between case 2 and 3 is much more subtle. Both version
differ call for the constructor and destructor. The only real
difference is that in case 3 you preallocate N*sizeof(T) bytes for
future use, while in case 2 you allcoate memory dynamically. It is
not obvious what strategy is better and more efficient. Even more -
using approrpiate allocator policy you could have at least the same
memory allocation strategy as with your optional. But also you can
have different strategies.

>
> Anyway, I understand your concern that for builtin and trivial PODs
the
> pointer implementation will add unnecesary overhead, but on the
other hand,
> with non trivial objects optional<> is better than smart_ptr<> in
that you
> skip the allocation/deallocation.
>
> Since I don't know how to support both versions without
complicating things
> (I don't like the policy-based approach, at least not yet),

Why? Policies are supposed to be used to be able to encopsulate
different implementation decisions: like kind of syncronization to be
used, memory allocation strategy, value storage strategy any other
behavioral decisions( like with iterator_adaptor - policy used to be
able change iterator behavior). So even I do not see to much use for
pointer based implementation for optional, this decision could be
encapsulated in some kind of policy.

> > > > > > [SNIP]
> >
> > > > C++ allows you to write int i = 3.14. If there is converstion
> > between
> > > > U and T ( so you can write T t = u;), we should be able to do
> > this:
> > > > optional<T> t; *t = u; In other case it will become even more
> > strict
> > > > limitation then DefaultContructable.
> > > >
> > > Actually, there is no limitation here. If there is a valid
> > conversion
> > > between U and T you can
> > > always do: optional<T> t ; *t = (T)u ;
> >
> > First of all in this form it is 2 times more work. You will need
to
> > call T(U) and than T(T).
> > That by itself sometimes could be
> > inacceptable.
> True. I note this as argument (1).
>
> > Another issue is that the difference is handwritten, th
> > at will prevent usage of optional in some cases. Example,
> >
> > Imagine you have existent template function like this:
> > template<typename T, typename U>
> > foo( T const& t, U const& u ) {
> > ...
> > if( t != u )
> > t = u;
> > ...
> > }
> >
> > optional<T> t; // was T* t; where NULL meant absent value
> > U u;
> >
> > ...
> >
> > if( !t )
> > foo( *t, u );
> >
> > Last line won't compile.
> >
> I note this as argument (2).
>
> Now,
> argument (2) is a template code that performs implicit conversion.
It is
> essentially equivalent to a templated assignment or copy
constructor.
> Though this code has the advantage that skips the extra ctor used
in the
> explicit cast (argument (1)), it is also a *big* source of
potential errors
> precisely because of the implicit conversion used.

You see, my concern is the back-compatibility. Let imagine we have a
programmer that was using pointer T* to manage value that can be
uninitialized. He has some existent code base. Now he want to switch
from T* to optional<T> to enchance a value access time. But some of
his functions where using expressions like *t = u. What do you think
he will be doing? Change all over the places to add probably costly
explicit cast (some of them could be inaccessable or third party) or
change optional.hpp to support implicit coversions?

I know what I would do.

>
> I recommend *strongly* against the kind of code of argument (2), so
I won't
> support conversion ctor or assigment, even at the expense of the
extra call
> that you properly noted in (1).
>
> > > Besides,
> > > I REALLY DON'T LIKE *THIS KIND* OF IMPLICIT CONVERSIONS.
> > >
> > > Just as I would recommend anyone never to write
> > > int i = 3.14, but eventually, int i = boost::numeric_cast<int>
> > (3.14),
> > > I won't support this implicit conversions in optional, not even
> > those
> > > supported by the language.
> >
> > Well, I may not like implicit conversions very much either. But
given
> > the fact that language allows that you can't avoid presence of
> > implicit convertion in generic transparent type like optional (at
> > least I think it should be transparent - should behave like T*)
in my
> > opinion.
> >
> IMHO, the language shouldn't allow this, then I won't.
>
> Fernando Cacciola
> Sierra s.r.l.
> fcacciola_at_g...
> www.gosierra.com

Gennadiy.


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