| 1 | <!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd"> |
|---|
| 2 | |
|---|
| 3 | <HTML> |
|---|
| 4 | |
|---|
| 5 | <HEAD> |
|---|
| 6 | <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
|---|
| 7 | <LINK REL="stylesheet" TYPE="text/css" HREF="../../boost.css"> |
|---|
| 8 | <TITLE>Header </TITLE> |
|---|
| 9 | </HEAD> |
|---|
| 10 | |
|---|
| 11 | <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080"> |
|---|
| 12 | <H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2> |
|---|
| 13 | |
|---|
| 14 | <blockquote> |
|---|
| 15 | <blockquote> |
|---|
| 16 | <blockquote> |
|---|
| 17 | <blockquote> |
|---|
| 18 | <blockquote> |
|---|
| 19 | <blockquote> |
|---|
| 20 | <H2 align="left">Header <<A |
|---|
| 21 | HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>> </H2> |
|---|
| 22 | |
|---|
| 23 | <H2 align="left">Header <<A |
|---|
| 24 | HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>> </H2> |
|---|
| 25 | |
|---|
| 26 | </blockquote> |
|---|
| 27 | </blockquote> |
|---|
| 28 | </blockquote> |
|---|
| 29 | </blockquote> |
|---|
| 30 | </blockquote> |
|---|
| 31 | </blockquote> |
|---|
| 32 | <p> </p> |
|---|
| 33 | |
|---|
| 34 | <H2>Contents</H2> |
|---|
| 35 | <DL CLASS="page-index"> |
|---|
| 36 | <DT><A HREF="#mot">Motivation</A></DT> |
|---|
| 37 | <DT><A HREF="#framework">Framework</A></DT> |
|---|
| 38 | <DT><A HREF="#specification">Specification</A></DT> |
|---|
| 39 | <DT><A HREF="#container-usage">Container-side Usage</A></DT> |
|---|
| 40 | <DT><A HREF="#user-usage">User-side Usage</A></DT> |
|---|
| 41 | </DL> |
|---|
| 42 | |
|---|
| 43 | <HR> |
|---|
| 44 | |
|---|
| 45 | <H2><A NAME="mot"></A>Motivation</H2> |
|---|
| 46 | |
|---|
| 47 | <p>Suppose we have a class</p> |
|---|
| 48 | <pre>struct X |
|---|
| 49 | { |
|---|
| 50 | X ( int, std:::string ) ; |
|---|
| 51 | } ;</pre> |
|---|
| 52 | <p>And a container for it which supports an empty state (that is, which can contain zero objects):</p> |
|---|
| 53 | <pre>struct C |
|---|
| 54 | { |
|---|
| 55 | C() : contained_(0) {} |
|---|
| 56 | ~C() { delete contained_ ; } |
|---|
| 57 | X* contained_ ; |
|---|
| 58 | } ;</pre> |
|---|
| 59 | <p>A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible, |
|---|
| 60 | but it typically requires it to be CopyConstructible as a mechanism to |
|---|
| 61 | initialize the object to store:</p> |
|---|
| 62 | <pre>struct C |
|---|
| 63 | { |
|---|
| 64 | C() : contained_(0) {} |
|---|
| 65 | C ( X const& v ) : contained_ ( new X(v) ) {} |
|---|
| 66 | ~C() { delete contained_ ; } |
|---|
| 67 | X* contained_ ; |
|---|
| 68 | } ;</pre> |
|---|
| 69 | <p>There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, |
|---|
| 70 | there must exist a previously constructed source object to copy from. This |
|---|
| 71 | object is likely to be temporary and serve no purpose besides being the source</p> |
|---|
| 72 | <pre>void foo() |
|---|
| 73 | { |
|---|
| 74 | // Temporary object created. |
|---|
| 75 | C c( X(123,"hello") ) ; |
|---|
| 76 | } |
|---|
| 77 | </pre> |
|---|
| 78 | <p>A solution to this problem is to support direct construction of the contained |
|---|
| 79 | object right in the container's storage.<br> |
|---|
| 80 | In this shceme, the user supplies the arguments for the X constructor |
|---|
| 81 | directly to the container:</p> |
|---|
| 82 | <pre>struct C |
|---|
| 83 | { |
|---|
| 84 | C() : contained_(0) {} |
|---|
| 85 | C ( X const& v ) : contained_ ( new X(v) ) {} |
|---|
| 86 | C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {} |
|---|
| 87 | ~C() { delete contained_ ; } |
|---|
| 88 | X* contained_ ; |
|---|
| 89 | } ;</pre> |
|---|
| 90 | <pre>void foo() |
|---|
| 91 | { |
|---|
| 92 | // Wrapped object constructed in-place |
|---|
| 93 | // No temporary created. |
|---|
| 94 | C c(123,"hello") ; |
|---|
| 95 | } |
|---|
| 96 | </pre> |
|---|
| 97 | <p>Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type |
|---|
| 98 | (at least all those which are to be supported directly in the container).</p> |
|---|
| 99 | |
|---|
| 100 | <H2><A NAME="framework"></A>Framework</H2> |
|---|
| 101 | <p> |
|---|
| 102 | This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring |
|---|
| 103 | the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible |
|---|
| 104 | requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br> |
|---|
| 105 | The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized). |
|---|
| 106 | Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override |
|---|
| 107 | a fully-constructed object (as this would defeat the purpose of in-place construction) |
|---|
| 108 | </p> |
|---|
| 109 | <p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br> |
|---|
| 110 | Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters. |
|---|
| 111 | Each member of the family differs only in the number (and type) of the parameter list. The first family |
|---|
| 112 | takes the type of the object to construct directly in method provided for that |
|---|
| 113 | purpose, whereas the second family incorporates that type in the factory class |
|---|
| 114 | itself..</p> |
|---|
| 115 | <p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place. |
|---|
| 116 | From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br> |
|---|
| 117 | The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p> |
|---|
| 118 | <pre>struct C |
|---|
| 119 | { |
|---|
| 120 | template<class InPlaceFactory> |
|---|
| 121 | C ( InPlaceFactory const& aFactoty ) |
|---|
| 122 | : |
|---|
| 123 | contained_ ( uninitialized_storage() ) |
|---|
| 124 | { |
|---|
| 125 | aFactory.template apply<X>(contained_); |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | ~C() |
|---|
| 129 | { |
|---|
| 130 | contained_ -> X::~X(); |
|---|
| 131 | delete[] contained_ ; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | char* uninitialized_storage() { return new char[sizeof(X)] ; } |
|---|
| 135 | |
|---|
| 136 | char* contained_ ; |
|---|
| 137 | } ; |
|---|
| 138 | |
|---|
| 139 | void foo() |
|---|
| 140 | { |
|---|
| 141 | C c( in_place(123,"hello" ) ; |
|---|
| 142 | } |
|---|
| 143 | </pre> |
|---|
| 144 | |
|---|
| 145 | <HR> |
|---|
| 146 | |
|---|
| 147 | <H2><A NAME="specification">Specification</A></H2> |
|---|
| 148 | |
|---|
| 149 | <p>The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function. |
|---|
| 150 | The rest of the family varies only in the number and type of template (and constructor) parameters.</p> |
|---|
| 151 | <PRE>namespace boost { |
|---|
| 152 | |
|---|
| 153 | struct in_place_factory_base {} ; |
|---|
| 154 | |
|---|
| 155 | template<class A0> |
|---|
| 156 | class in_place_factory : public in_place_factory_base |
|---|
| 157 | { |
|---|
| 158 | public:</PRE> |
|---|
| 159 | |
|---|
| 160 | <PRE> in_place_factory ( A0 const& a0 ) : m_a0(a0) {} |
|---|
| 161 | |
|---|
| 162 | template< class T > |
|---|
| 163 | void apply ( void* address ) const |
|---|
| 164 | { |
|---|
| 165 | new (address) T(m_a0); |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | private:</PRE> |
|---|
| 169 | |
|---|
| 170 | <PRE> A0 const& m_a0 ; |
|---|
| 171 | } ; |
|---|
| 172 | |
|---|
| 173 | template<class A0> |
|---|
| 174 | in_place_factory<A0> in_place ( A0 const& a0 ) |
|---|
| 175 | { |
|---|
| 176 | return in_place_factory<A0>(a0); |
|---|
| 177 | } |
|---|
| 178 | </PRE> |
|---|
| 179 | |
|---|
| 180 | <p>Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding |
|---|
| 181 | helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.</p> |
|---|
| 182 | <PRE>namespace boost { |
|---|
| 183 | |
|---|
| 184 | struct typed_in_place_factory_base {} ; |
|---|
| 185 | |
|---|
| 186 | template<class T, class A0> |
|---|
| 187 | class typed_in_place_factory : public typed_in_place_factory_base |
|---|
| 188 | { |
|---|
| 189 | public:</PRE> |
|---|
| 190 | |
|---|
| 191 | <PRE> typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {} |
|---|
| 192 | |
|---|
| 193 | void apply ( void* address ) const |
|---|
| 194 | { |
|---|
| 195 | new (address) T(m_a0); |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | private:</PRE> |
|---|
| 199 | |
|---|
| 200 | <PRE> A0 const& m_a0 ; |
|---|
| 201 | } ; |
|---|
| 202 | |
|---|
| 203 | template<class T, class A0> |
|---|
| 204 | typed_in_place_factory<A0> in_place ( A0 const& a0 ) |
|---|
| 205 | { |
|---|
| 206 | return typed_in_place_factory<T,A0>(a0); |
|---|
| 207 | }</PRE> |
|---|
| 208 | |
|---|
| 209 | <PRE>} |
|---|
| 210 | </PRE> |
|---|
| 211 | |
|---|
| 212 | <p>As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify |
|---|
| 213 | the target type: in the first family, the type is given as a template argument to the apply member function while in the |
|---|
| 214 | second it is given directly as part of the factory class.<br> |
|---|
| 215 | When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type |
|---|
| 216 | of the contained object and can pass it to the apply() method of a (non-typed) factory. |
|---|
| 217 | In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br> |
|---|
| 218 | However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type |
|---|
| 219 | of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory' |
|---|
| 220 | instead.</p> |
|---|
| 221 | |
|---|
| 222 | <HR> |
|---|
| 223 | |
|---|
| 224 | <h2><A NAME="container-usage">Container-side Usage</a></h2> |
|---|
| 225 | |
|---|
| 226 | <p>As shown in the introductory simplified example, the container class must |
|---|
| 227 | contain methods that accept an instance of |
|---|
| 228 | these factories and pass the object's storage to the factory's apply method.<br> |
|---|
| 229 | However, the type of the factory class cannot be completly specified in the container class because that would |
|---|
| 230 | defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list |
|---|
| 231 | for the constructor of its contained object.<br> |
|---|
| 232 | The correct function overload must be based on the only distinctive and common |
|---|
| 233 | characteristic of all the classes in each family, the base class.<br> |
|---|
| 234 | Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following |
|---|
| 235 | dispatch technique (used in the Boost.Optional class): |
|---|
| 236 | </p> |
|---|
| 237 | <pre>struct C |
|---|
| 238 | { |
|---|
| 239 | C() : contained_(0) {} |
|---|
| 240 | C ( X const& v ) : contained_ ( new X(v) ) {} |
|---|
| 241 | |
|---|
| 242 | template<class Expr> |
|---|
| 243 | C ( Expr const& expr ) |
|---|
| 244 | : |
|---|
| 245 | contained_ ( uninitialized_storage() ) |
|---|
| 246 | { |
|---|
| 247 | construct(expr,&expr) |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | ~C() { delete contained_ ; } |
|---|
| 251 | |
|---|
| 252 | template<class InPlaceFactory> |
|---|
| 253 | void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* ) |
|---|
| 254 | { |
|---|
| 255 | aFactory.template apply<X>(contained_); |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | template<class TypedInPlaceFactory> |
|---|
| 259 | void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* ) |
|---|
| 260 | { |
|---|
| 261 | aFactory.apply(contained_); |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; } |
|---|
| 265 | |
|---|
| 266 | X* contained_ ; |
|---|
| 267 | } ; |
|---|
| 268 | </pre> |
|---|
| 269 | |
|---|
| 270 | <hr> |
|---|
| 271 | |
|---|
| 272 | <h2><A NAME="user-usage">User-side Usage</a></h2> |
|---|
| 273 | |
|---|
| 274 | <p>End users pass to the container an instance of a factory object holding the actual parameters needed to construct the |
|---|
| 275 | contained object directly within the container. For this, the helper template function 'in_place' is used.<br> |
|---|
| 276 | The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br> |
|---|
| 277 | The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the |
|---|
| 278 | type 'T'.</p> |
|---|
| 279 | <pre>void foo() |
|---|
| 280 | { |
|---|
| 281 | C a( in_place(123,"hello") ) ; // in_place_factory passed |
|---|
| 282 | C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed |
|---|
| 283 | } |
|---|
| 284 | </pre> |
|---|
| 285 | |
|---|
| 286 | <P>Revised September 17, 2004</P> |
|---|
| 287 | <p>© Copyright Fernando Luis Cacciola Carballal, 2004</p> |
|---|
| 288 | <p> Use, modification, and distribution are subject to the Boost Software |
|---|
| 289 | License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt"> |
|---|
| 290 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> |
|---|
| 291 | www.boost.org/LICENSE_1_0.txt</a>)</p> |
|---|
| 292 | <P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>, |
|---|
| 293 | the latest version of this file can be found at <A |
|---|
| 294 | HREF="http://www.boost.org">www.boost.org</A>, and the boost |
|---|
| 295 | <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P> |
|---|
| 296 | </BODY> |
|---|
| 297 | </HTML> |
|---|