Boost logo

Boost :

From: Andrey Melnikov (melnikov_at_[hidden])
Date: 2005-07-13 10:49:24


Jost, Andrew wrote:

> a better implementation of guaranteed delivery would
> make use of template function objects that I'll call "adapters". The
> role of an adapter would be to evaluate a given optional object (I'll
> refer to anything resembling Boost.Optional as an "optional" object)
> into either the valid object it contains, or a default value, which is
> probably defined in the adapter's template specification or constructor.
> Adapters separate our optional objects from the defaults we might want
> to use in place of uninitialized T objects. Note that they are
> incompatible with noncopyable T objects.
>
> Using adapters, the call to trend::loadPoint in the first example might
> look like this:
>
>
> // -- begin
> // call trend::loadPoint
> opt_dp::adapter f(-1);
> for( data_set::iterator p = d.begin(); p != d.end(); ++p ) {
> tr.loadPoint( f(*p) );
> }
> // -- end
>

Adapters don't have to require copyable objects. A specialization can
deal with noncopyable objects by replacing requirement to underlying
type to be copyable with requirement to client code to accept const
references and don't require identity semantic. Also, the adapter should
live until it's default value is used somewhere.

Here is pseudo-code:

-------
const T & adapter<T>::adapter(<constructor_parameters>) :
default_value_member(<constructor_parameters>)
{
}

const T & adapter<T>::adapt(const T & value_to_adapt)
{
     return value_to_adapt ? value_to_adapt : default_value_member;
}
-------

I think because this flavour of adapter manages the lifetime of
contained default value, it's possible to build a version which would
manage a container of multiple "default" objects and would enable
identity semantic and remove const requirement. I don't think if this
exotic case will be useful though.

Also it's possible to decouple the adapter from its managed default
value object by using

MO managed_object;
// accepts, stores and returns a reference
adapter<MO> f(managed_object);

Also default values don't have to be constants. Default objects can be
generated by a generator object (which produces values) or by a factory
(which produces identities and may allocate memory). For example,
sometimes a random or "next free" default value can be useful. Like in
case of bind() TCP socket function with optional port number.

And finally, it's possible to relax the requirements to both underlying
objects (T) and client code (loadPoint) by storing a reference to an
inplace factory inside of Optional objects, but as a price for this
improvement we are back to that "metadata binding sin" then.

Or we can allow adapters simply to modify underlying objects:

adapter<MO> f(<inplace factory for default values>);

What do you think about all these proposed adapter designs?

Andrey


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