• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[/
2Copyright 2007,2008 Tobias Schwinger
3
4Copyright 2019 Glen Joseph Fernandes
5(glenjofe@gmail.com)
6
7Distributed under the Boost Software License, Version 1.0.
8(http://www.boost.org/LICENSE_1_0.txt)
9]
10
11[library Boost.Functional/Factory
12[quickbook 1.5]
13[version 1.0]
14[authors [Schwinger, Tobias], [Fernandes, Glen]]
15[copyright 2007 2008 Tobias Schwinger]
16[copyright 2019 Glen Joseph Fernandes]
17[license Distributed under the Boost Software License, Version 1.0.]
18[purpose Function object templates for object creation.]
19[category higher-order]
20[category generic]]
21
22[def __boost__bind__
23[@http://www.boost.org/libs/bind/bind.html `boost::bind`]]
24
25[def __boost__forward_adapter__
26[@http://www.boost.org/libs/functional/forward/doc/index.html
27`boost::forward_adapter`]]
28
29[def __boost_function__
30[@http://www.boost.org/doc/html/function.html Boost.Function]]
31
32[def __smart_pointer__
33[@http://www.boost.org/libs/smart_ptr/index.html Smart Pointer]]
34
35[def __smart_pointers__
36[@http://www.boost.org/libs/smart_ptr/index.html Smart Pointers]]
37
38[def __boost__shared_ptr__
39[@http://www.boost.org/libs/smart_ptr/shared_ptr.htm `boost::shared_ptr`]]
40
41[def __allocator__ [@https://www.boost.org/sgi/stl/Allocators.html Allocator]]
42
43[def __std_allocators__
44[@https://www.boost.org/sgi/stl/Allocators.html Allocators]]
45
46[def __boost__factory__ `boost::factory`]
47
48[def __boost__value_factory__ `boost::value_factory`]
49
50[def __value_factory__ `value_factory`]
51
52[section Brief Description]
53
54The template __boost__factory__ lets you encapsulate a `new` expression as a
55function object, __boost__value_factory__ encapsulates a constructor invocation
56without `new`.
57
58```
59__boost__factory__<T*>()(arg1,arg2,arg3)
60// same as new T(arg1,arg2,arg3)
61
62__boost__value_factory__<T>()(arg1,arg2,arg3)
63// same as T(arg1,arg2,arg3)
64```
65
66Before C++11 the arguments to the function objects have to be LValues. A
67factory that also accepts RValues can be composed using the
68__boost__forward_adapter__ or __boost__bind__. In C++11 or higher the
69arguments can be LValues or RValues.
70
71[endsect]
72
73[section Background]
74
75In traditional Object Oriented Programming a Factory is an object implementing
76an interface of one or more methods that construct objects conforming to known
77interfaces.
78
79```
80// assuming a_concrete_class and another_concrete_class are derived
81// from an_abstract_class
82
83struct a_factory {
84    virtual an_abstract_class* create() const = 0;
85    virtual ~a_factory() { }
86};
87
88struct a_concrete_factory
89    : a_factory {
90    an_abstract_class* create() const {
91        return new a_concrete_class();
92    }
93};
94
95struct another_concrete_factory
96    : a_factory {
97    an_abstract_class* create() const {
98        return new another_concrete_class();
99    }
100};
101
102// [...]
103
104int main()
105{
106    boost::ptr_map<std::string, a_factory> factories;
107
108    // [...]
109
110    factories.insert("a_name",
111        std::unique_ptr<a_factory>(new a_concrete_factory));
112    factories.insert("another_name",
113        std::unique_ptr<a_factory>(new another_concrete_factory));
114
115    // [...]
116
117    std::unique_ptr<an_abstract_class> x(factories.at(some_name).create());
118
119    // [...]
120}
121```
122
123This approach has several drawbacks. The most obvious one is that there is lots
124of boilerplate code. In other words there is too much code to express a rather
125simple intention. We could use templates to get rid of some of it but the
126approach remains inflexible:
127
128* We may want a factory that takes some arguments that are forwarded to the
129constructor,
130* we will probably want to use smart pointers,
131* we may want several member functions to create different kinds of objects,
132* we might not necessarily need a polymorphic base class for the objects,
133* as we will see, we do not need a factory base class at all,
134* we might want to just call the constructor - without `new` to create an
135object on the stack, and
136* finally we might want to use customized memory management.
137
138Experience has shown that using function objects and generic Boost components
139for their composition, Design Patterns that describe callback mechanisms
140(typically requiring a high percentage of boilerplate code with pure Object
141Oriented methodology) become implementable with just few code lines and without
142extra classes.
143
144Factories are callback mechanisms for constructors, so we provide two class
145templates, __boost__value_factory__ and __boost__factory__, that encapsulate
146object construction via direct application of the constructor and the `new`
147operator, respectively.
148
149We let the function objects forward their arguments to the construction
150expressions they encapsulate. Over this __boost__factory__ optionally allows
151the use of smart pointers and __std_allocators__.
152
153Compile-time polymorphism can be used where appropriate,
154
155```
156template<class T>
157void do_something()
158{
159    // [...]
160    T x = T(a, b);
161
162    // for conceptually similar objects x we neither need virtual
163    // functions nor a common base class in this context.
164    // [...]
165}
166```
167
168Now, to allow inhomogeneous signatures for the constructors of the types passed
169in for `T` we can use __value_factory__ and __boost__bind__ to normalize
170between them.
171
172```
173template<class ValueFactory>
174void do_something(ValueFactory make_obj = ValueFactory())
175{
176    // [...]
177    typename ValueFactory::result_type x = make_obj(a, b);
178
179    // for conceptually similar objects x we neither need virtual
180    // functions nor a common base class in this context.
181    // [...]
182}
183
184int main()
185{
186    // [...]
187
188    do_something(boost::value_factory<X>());
189    do_something(boost::bind(boost::value_factory<Y>(), _1, 5, _2));
190    // construct X(a, b) and Y(a, 5, b), respectively.
191
192    // [...]
193}
194```
195
196Maybe we want our objects to outlive the function's scope, in this case we have
197to use dynamic allocation;
198
199```
200template<class Factory>
201whatever do_something(Factory new_obj = Factory())
202{
203    typename Factory::result_type ptr = new_obj(a, b);
204
205    // again, no common base class or virtual functions needed,
206    // we could enforce a polymorphic base by writing e.g.
207    //     boost::shared_ptr<base>
208    // instead of
209    //     typename Factory::result_type
210    // above.
211    // Note that we are also free to have the type erasure happen
212    // somewhere else (e.g. in the constructor of this function's
213    // result type).
214
215    // [...]
216}
217
218// [... call do_something like above but with boost::factory instead
219// of boost::value_factory]
220```
221
222Although we might have created polymorphic objects in the previous example, we
223have used compile time polymorphism for the factory. If we want to erase the
224type of the factory and thus allow polymorphism at run time, we can use
225__boost_function__ to do so. The first example can be rewritten as follows.
226
227```
228typedef boost::function<an_abstract_class*()> a_factory;
229
230// [...]
231
232int main()
233{
234    std::map<std::string, a_factory> factories;
235
236    // [...]
237
238    factories["a_name"] = boost::factory<a_concrete_class*>();
239    factories["another_name"] = boost::factory<another_concrete_class*>();
240
241    // [...]
242}
243```
244
245Of course we can just as easy create factories that take arguments and/or
246return __smart_pointers__.
247
248[endsect]
249
250[section:reference Reference]
251
252[section value_factory]
253
254[heading Description]
255
256Function object template that invokes the constructor of the type `T`.
257
258[heading Header]
259
260```
261#include <boost/functional/value_factory.hpp>
262```
263
264[heading Synopsis]
265
266```
267namespace boost {
268
269template<class T>
270class value_factory;
271
272} // boost
273```
274
275[variablelist Notation
276[[`T`][an arbitrary type with at least one public constructor]]
277[[`a0`...`aN`][argument values to a constructor of `T`]]
278[[`F`][the type `value_factory<F>`]]
279[[`f`][an instance object of `F`]]]
280
281[heading Expression Semantics]
282
283[table
284[[Expression][Semantics]]
285[[`F()`][creates an object of type `F`.]]
286[[`F(f)`][creates an object of type `F`.]]
287[[`f(a0`...`aN)`][returns `T(a0`...`aN)`.]]
288[[`F::result_type`][is the type `T`.]]]
289
290[heading Limits]
291
292Before C++11, the maximum number of arguments supported is 10. Since C++11 an
293arbitrary number of arguments is supported.
294
295[endsect]
296
297[section factory]
298
299[heading Description]
300
301Function object template that dynamically constructs a pointee object for the
302type of pointer given as template argument. Smart pointers may be used for the
303template argument, given that `pointer_traits<Pointer>::element_type` yields
304the pointee type.
305
306If an __allocator__ is given, it is used for memory allocation and the
307placement form of the `new` operator is used to construct the object. A
308function object that calls the destructor and deallocates the memory with a
309copy of the Allocator is used for the second constructor argument of `Pointer`
310(thus it must be a __smart_pointer__ that provides a suitable constructor,
311such as __boost__shared_ptr__).
312
313If a third template argument is `factory_passes_alloc_to_smart_pointer`, the
314allocator itself is used for the third constructor argument of `Pointer`
315(__boost__shared_ptr__ then uses the allocator to manage the memory of its
316separately allocated reference counter).
317
318[heading Header]
319
320```
321#include <boost/functional/factory.hpp>
322```
323
324[heading Synopsis]
325
326```
327namespace boost {
328
329enum factory_alloc_propagation {
330    factory_alloc_for_pointee_and_deleter,
331    factory_passes_alloc_to_smart_pointer
332};
333
334template<class Pointer,
335    class Allocator = void,
336    factory_alloc_propagation Policy = factory_alloc_for_pointee_and_deleter>
337class factory;
338
339} // boost
340```
341
342[variablelist Notation
343[[`T`][an arbitrary type with at least one public constructor]]
344[[`P`][pointer or smart pointer to `T`]]
345[[`a0`...`aN`][argument values to a constructor of `T`]]
346[[`F`][the type `factory<P>`]]
347[[`f`][an instance object of `F`]]]
348
349[heading Expression Semantics]
350
351[table
352[[Expression][Semantics]]
353[[`F()`][creates an object of type `F`.]]
354[[`F(f)`][creates an object of type `F`.]]
355[[`f(a0`...`aN)`]
356[dynamically creates an object of type `T` using `a0`...`aN` as arguments for
357the constructor invocation.]]
358[[`F::result_type`][is the type `P` with top-level cv-qualifiers removed.]]]
359
360[heading Limits]
361
362Before C++11, the maximum number of arguments supported is 10. Since C++11 an
363arbitrary number of arguments is supported.
364
365[endsect]
366
367[endsect]
368
369[section Changes]
370
371[heading Boost 1.72.0]
372
373Glen Fernandes rewrote the implementations of `factory` and `value_factory` to
374provide the following features:
375
376* Support r-value arguments when available
377* Support arbitrary number of arguments via variadic templates when available
378* Support allocators that are final
379* Support allocators that use fancy pointers
380* Support for disabled exceptions (`BOOST_NO_EXCEPTIONS`)
381* Improved compilation times
382
383The following features have been removed:
384
385* Increasing limits for C++03 compilers through
386  `BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY`
387* Using `boost::none_t` in place of `void` through
388  `BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T`
389
390[heading Boost 1.58.0]
391
392In order to remove the dependency on Boost.Optional, the default parameter for
393allocators has been changed from `boost::none_t` to `void`. If you have code
394that has stopped working because it uses `boost::none_t`, a quick fix is to
395define `BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T`, which will restore support,
396but this will be removed in a future release. It should be be relatively easy
397to fix this properly.
398
399[endsect]
400
401[section Acknowledgements]
402
403Tobias Schwinger for creating this library.
404
405Eric Niebler requested a function to invoke a type's constructor (with the
406arguments supplied as a Tuple) as a Fusion feature. These Factory utilities are
407a factored-out generalization of this idea.
408
409Dave Abrahams suggested Smart Pointer support for exception safety, providing
410useful hints for the implementation.
411
412Joel de Guzman's documentation style was copied from Fusion.
413
414Peter Dimov for sharing his insights on language details and their evolution.
415
416[endsect]
417
418[section References]
419
420# [@http://en.wikipedia.org/wiki/Design_Patterns Design Patterns],
421Gamma et al. - Addison Wesley Publishing, 1995
422
423# [@https://boost.org/sgi/stl/ Standard Template Library Programmer's Guide],
424Hewlett-Packard Company, 1994
425
426# [@http://www.boost.org/libs/bind/bind.html Boost.Bind],
427Peter Dimov, 2001-2005
428
429# [@http://www.boost.org/doc/html/function.html Boost.Function],
430Douglas Gregor, 2001-2004
431
432[endsect]
433