Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/utility/in_place_factories.html @ 47

Last change on this file since 47 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.5 KB
Line 
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 &lt;<A
21HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>&gt; </H2>
22
23<H2 align="left">Header &lt;<A
24HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>&gt; </H2>
25
26          </blockquote>
27        </blockquote>
28      </blockquote>
29    </blockquote>
30  </blockquote>
31</blockquote>
32<p>&nbsp;</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,
60but it typically requires it to be CopyConstructible as a mechanism to
61initialize 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,
70there must exist a previously constructed source object to copy from. This
71object 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
79object right in the container's storage.<br>
80In this shceme, the user supplies the arguments for the X constructor
81directly 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>
102This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring
103the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible
104requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br>
105The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized).
106Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override
107a 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>
110Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters.
111Each member of the family differs only in the number (and type) of the parameter list. The first family
112takes the type of the object to construct directly in method provided for that
113purpose, whereas the second family incorporates that type in the factory class
114itself..</p>
115<p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place.
116From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br>
117The 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&lt;class InPlaceFactory&gt;
121   C ( InPlaceFactory const& aFactoty )
122    :
123    contained_ ( uninitialized_storage() )
124   {
125     aFactory.template apply&lt;X&gt;(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
139void 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.
150The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
151<PRE>namespace boost {
152
153struct in_place_factory_base {} ;
154
155template&lt;class A0&gt;
156class 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&lt; class T &gt;
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
173template&lt;class A0&gt;
174in_place_factory&lt;A0&gt; in_place ( A0 const& a0 )
175{
176  return in_place_factory&lt;A0&gt;(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
181helper 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
184struct typed_in_place_factory_base {} ;
185
186template&lt;class T, class A0&gt;
187class 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
203template&lt;class T, class A0&gt;
204typed_in_place_factory&lt;A0&gt; in_place ( A0 const& a0 )
205{
206  return typed_in_place_factory&lt;T,A0&gt;(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
213the target type: in the first family, the type is given as a template argument to the apply member function while in the
214second it is given directly as part of the factory class.<br>
215When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type
216of the contained object and can pass it to the apply() method of a (non-typed) factory.
217In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br>
218However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type
219of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory'
220instead.</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
227contain methods that accept an instance of
228these factories and pass the object's storage to the factory's apply method.<br>
229However, the type of the factory class cannot be completly specified in the container class because that would
230defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
231for the constructor of its contained object.<br>
232The correct function overload must be based on the only distinctive and common
233characteristic of all the classes in each family, the base class.<br>
234Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following
235dispatch 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&lt;class Expr&gt
243   C ( Expr const& expr )
244    :
245    contained_ ( uninitialized_storage() )
246   {
247    construct(expr,&expr)
248   }
249
250  ~C() { delete contained_ ; }
251
252  template&lt;class InPlaceFactory&gt;
253  void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
254  {
255    aFactory.template apply&lt;X&gt;(contained_);
256  }
257
258  template&lt;class TypedInPlaceFactory&gt;
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&lt;X*&gt;(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
275contained object directly within the container. For this, the helper template function 'in_place' is used.<br>
276The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br>
277The call 'in_place&lt;T&gt;(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the
278type 'T'.</p>
279<pre>void foo()
280{
281  C a( in_place(123,"hello") ) ;    // in_place_factory passed
282  C b( in_place&lt;X&gt;(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
289License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
290LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
291www.boost.org/LICENSE_1_0.txt</a>)</p>
292<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
293the latest version of this file can be found at <A
294HREF="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>
Note: See TracBrowser for help on using the repository browser.