Boost logo

Boost :

From: Fernando Cacciola \(Home\) (fernando_cacciola_at_[hidden])
Date: 2003-02-13 10:06:10


----- Original Message -----
From: "Anthony Williams" <anthony.williamsNOSPAM_at_[hidden]>
To: "Boost mailing list" <boost_at_[hidden]>
Sent: Thursday, February 13, 2003 7:05 AM
Subject: Re: [boost] 'optional' - request for extension

> Aleksey Gurtovoy writes:
> >
> > The following is a sketch of a potential use case for the
newly-accepted and
> > already very useful 'optional' class.
> >
I'm glad to see optional<> being already exercised!

> > Suppose you have a pure RAII guard/locker which unconditionally does
its
> > job:
> >
> > struct RAII_lock
> > : boost::noncopyable
> > {
> > RAII_lock(entity& e);
> > ~RAII_lock();
> > };
> >
> > and you want to write a semantic equivalent to the following
> >
> > boost::scoped_ptr<RAII_lock> lock( cond ? new RAII_lock(entity) :
0 );
> > // ...
> >
> > expect for the dynamic allocation part. How would you do it?
> >
> > IMO the following seems only natural:
> >
> > boost::optional<RAII_lock> lock( cond, entity );
> > // ...
> >
> > The only problem with the above is that currently you cannot write
something
> > like this. It would be nice if we could, IMO.
> >
> > Thoughts?
>
OK, I can see the motivation: We can have a noncopyable class
and need an optional object of it.
Following optional semantics, it would be spelled:

boost::optional<RAII_lock> lock;
if ( cond )
  lock.reset( RAII_lock(entity) ) ;

But there is a probem: as William pointed out, reset() _needs_
to use T::T(T const&) in order acquire its own copy of the object;
but in this case is noncopyable, so the above won't compile.

> * Firstly, this would require optional to be able hold
non-copy-constructible
> types, whereas the current requirement say "T must be CopyConstructible".
>
Indeed.

> You could drop the "CopyConstructible" requirement if you said that
> boost::optional<T> is only itself CopyConstructible/Assignable/Swappable
if T
> is CopyConstructible.
Right.

>However, this leaves the question of how to get the
> value in there in the first place; the answer to which is ...
>
With the current implementation it is possible to construct the contained
object in-place.

> * Secondly, you would need a templated constructor to allow T to be
constructed
> using another type.
>
Exactly.
One possibility would be add additional templated ctor and reset that just
forward the arguments to T's contructor
(optional's interface could use a trailing tag to differentiate these).

A problem with this is that the Argument Forwarding problem is burried
into optional's itself.
Another approach would be to create a generic delay-factory object and just
let
optional use it:

Something like:

template<class T, class A0>
struct in_place_factory0
{
  in_place_factory0 ( A0& a0_ ) : a0(a0_) {}

  T* operator() ( void* address ) const { return new (address) T(a0) ; }

  A0& a0 ;
} ;

template<class T, class A0>
in_place_factory0<T,A0> in_place ( A0& a0 ) { return
in_place_factory0<T,A0>(a0) ; }

which requires the following changes in optional<>:

  template<class T>
  class optional
  {
    public :

      ....

      template<class Factory>
      explicit optional ( Factory f )
        :
        m_initialized(false)
      {
        construct_inplace(f);
      }

      ...

    private :

      template<class Factory>
      void construct_inplace ( Factory f )
       {
         f(m_storage.address());
         m_initialized = true ;
       }
  } ;

The above would allow something like this:

optional<RAII_lock> l( in_place<RAII_lock>(entity) );

If the same in-place idiom is used on reset(), the complete
solution will look, following optional<>'s way:

boost::optional<RAII_lock> lock;
if ( cond )
  lock.reset( in_place(entity) );

What do you think?

Fernando Cacciola


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