1 2[section In-Place Factories] 3 4One of the typical problems with wrappers and containers is that their 5interfaces usually provide an operation to initialize or assign the 6contained object as a copy of some other object. This not only requires the 7underlying type to be __COPY_CONSTRUCTIBLE__, but also requires the existence of 8a fully constructed object, often temporary, just to follow the copy from: 9 10 struct X 11 { 12 X ( int, std::string ) ; 13 } ; 14 15 class W 16 { 17 X wrapped_ ; 18 19 public: 20 21 W ( X const& x ) : wrapped_(x) {} 22 } ; 23 24 void foo() 25 { 26 // Temporary object created. 27 W ( X(123,"hello") ) ; 28 } 29 30A solution to this problem is to support direct construction of the 31contained object right in the container's storage. 32In this scheme, the user only needs to supply the arguments to the 33constructor to use in the wrapped object construction. 34 35 class W 36 { 37 X wrapped_ ; 38 39 public: 40 41 W ( X const& x ) : wrapped_(x) {} 42 W ( int a0, std::string a1) : wrapped_(a0,a1) {} 43 } ; 44 45 void foo() 46 { 47 // Wrapped object constructed in-place 48 // No temporary created. 49 W (123,"hello") ; 50 } 51 52A limitation of this method is that it doesn't scale well to wrapped 53objects with multiple constructors nor to generic code were the constructor 54overloads are unknown. 55 56The solution presented in this library is the family of [*InPlaceFactories] 57and [*TypedInPlaceFactories]. 58These factories are a family of classes which encapsulate an increasing 59number of arbitrary constructor parameters and supply a method to construct 60an object of a given type using those parameters at an address specified by 61the user via placement new. 62 63For example, one member of this family looks like: 64 65 template<class T,class A0, class A1> 66 class TypedInPlaceFactory2 67 { 68 A0 m_a0 ; A1 m_a1 ; 69 70 public: 71 72 TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {} 73 74 void construct ( void* p ) { new (p) T(m_a0,m_a1) ; } 75 } ; 76 77A wrapper class aware of this can use it as: 78 79 class W 80 { 81 X wrapped_ ; 82 83 public: 84 85 W ( X const& x ) : wrapped_(x) {} 86 W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; } 87 } ; 88 89 void foo() 90 { 91 // Wrapped object constructed in-place via a TypedInPlaceFactory. 92 // No temporary created. 93 W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ; 94 } 95 96The factories are divided in two groups: 97 98* [_TypedInPlaceFactories]: those which take the target type as a primary 99template parameter. 100* [_InPlaceFactories]: those with a template `construct(void*)` member 101function taking the target type. 102 103Within each group, all the family members differ only in the number of 104parameters allowed. 105 106This library provides an overloaded set of helper template functions to 107construct these factories without requiring unnecessary template parameters: 108 109 template<class A0,...,class AN> 110 InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ; 111 112 template<class T,class A0,...,class AN> 113 TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ; 114 115In-place factories can be used generically by the wrapper and user as follows: 116 117 class W 118 { 119 X wrapped_ ; 120 121 public: 122 123 W ( X const& x ) : wrapped_(x) {} 124 125 template< class InPlaceFactory > 126 W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; } 127 128 } ; 129 130 void foo() 131 { 132 // Wrapped object constructed in-place via a InPlaceFactory. 133 // No temporary created. 134 W ( in_place(123,"hello") ) ; 135 } 136 137The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__ 138 139[endsect] 140