|
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