123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
-
- [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]
|