blob: d9df24d06457e62acb0daac8d7c92a34eab5516d [file] [log] [blame]

[section In-Place Factories]
One of the typical problems with wrappers and containers is that their
interfaces usually provide an operation to initialize or assign the
contained object as a copy of some other object. This not only requires the
underlying type to be __COPY_CONSTRUCTIBLE__, but also requires the existence of
a fully constructed object, often temporary, just to follow the copy from:
struct X
{
X ( int, std::string ) ;
} ;
class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
} ;
void foo()
{
// Temporary object created.
W ( X(123,"hello") ) ;
}
A solution to this problem is to support direct construction of the
contained object right in the container's storage.
In this scheme, the user only needs to supply the arguments to the
constructor to use in the wrapped object construction.
class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( int a0, std::string a1) : wrapped_(a0,a1) {}
} ;
void foo()
{
// Wrapped object constructed in-place
// No temporary created.
W (123,"hello") ;
}
A limitation of this method is that it doesn't scale well to wrapped
objects with multiple constructors nor to generic code were the constructor
overloads are unknown.
The solution presented in this library is the family of [*InPlaceFactories]
and [*TypedInPlaceFactories].
These factories are a family of classes which encapsulate an increasing
number of arbitrary constructor parameters and supply a method to construct
an object of a given type using those parameters at an address specified by
the user via placement new.
For example, one member of this family looks like:
template<class T,class A0, class A1>
class TypedInPlaceFactory2
{
A0 m_a0 ; A1 m_a1 ;
public:
TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
} ;
A wrapper class aware of this can use it as:
class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
} ;
void foo()
{
// Wrapped object constructed in-place via a TypedInPlaceFactory.
// No temporary created.
W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
}
The factories are divided in two groups:
* [_TypedInPlaceFactories]: those which take the target type as a primary
template parameter.
* [_InPlaceFactories]: those with a template `construct(void*)` member
function taking the target type.
Within each group, all the family members differ only in the number of
parameters allowed.
This library provides an overloaded set of helper template functions to
construct these factories without requiring unnecessary template parameters:
template<class A0,...,class AN>
InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
template<class T,class A0,...,class AN>
TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;
In-place factories can be used generically by the wrapper and user as follows:
class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
template< class InPlaceFactory >
W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
} ;
void foo()
{
// Wrapped object constructed in-place via a InPlaceFactory.
// No temporary created.
W ( in_place(123,"hello") ) ;
}
The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__
[endsect]