mirror of
https://github.com/boostorg/functional.git
synced 2025-08-01 21:44:28 +02:00
adds Functional/Factory
[SVN r61596]
This commit is contained in:
20
factory/doc/Jamfile
Normal file
20
factory/doc/Jamfile
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
# (C) Copyright Tobias Schwinger
|
||||
#
|
||||
# Use modification and distribution are subject to the boost Software License,
|
||||
# Version 1.0. (See http:/\/www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
using quickbook ;
|
||||
|
||||
xml factory : factory.qbk ;
|
||||
boostbook standalone : factory
|
||||
:
|
||||
<xsl:param>boost.root=../../../../..
|
||||
<xsl:param>boost.libraries=../../../../libraries.htm
|
||||
<xsl:param>chunk.section.depth=0
|
||||
<xsl:param>chunk.first.sections=0
|
||||
<xsl:param>generate.section.toc.level=2
|
||||
<xsl:param>toc.max.depth=1
|
||||
;
|
||||
|
||||
|
384
factory/doc/factory.qbk
Normal file
384
factory/doc/factory.qbk
Normal file
@@ -0,0 +1,384 @@
|
||||
[library Boost.Functional/Factory
|
||||
[quickbook 1.3]
|
||||
[version 1.0]
|
||||
[authors [Schwinger, Tobias]]
|
||||
[copyright 2007 2008 Tobias Schwinger]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
[purpose Function object templates for object creation.]
|
||||
[category higher-order]
|
||||
[category generic]
|
||||
[last-revision $Date: 2008/11/01 21:44:52 $]
|
||||
]
|
||||
|
||||
[def __boost_bind__ [@http://www.boost.org/libs/bind/bind.html Boost.Bind]]
|
||||
[def __boost__bind__ [@http://www.boost.org/libs/bind/bind.html `boost::bind`]]
|
||||
|
||||
[def __boost__forward_adapter__ [@http://www.boost.org/libs/functional/forward/doc/index.html `boost::forward_adapter`]]
|
||||
[def __fusion_functional_adapters__ [@http://www.boost.org/libs/fusion/doc/html/functional.html Fusion Functional Adapters]]
|
||||
|
||||
[def __boost_function__ [@http://www.boost.org/doc/html/function.html Boost.Function]]
|
||||
[def __boost__function__ [@http://www.boost.org/doc/html/function.html `boost::function`]]
|
||||
|
||||
[def __smart_pointers__ [@http://www.boost.org/libs/smart_ptr/index.html Smart Pointers]]
|
||||
[def __boost__shared_ptr__ [@http://www.boost.org/libs/smart_ptr/shared_ptr.htm `boost::shared_ptr`]]
|
||||
|
||||
[def __std__map__ [@http://www.sgi.com/tech/stl/map.html `std::map`]]
|
||||
[def __std__string__ [@http://www.sgi.com/tech/stl/string.html `std::string`]]
|
||||
[def __std_allocator__ [@http://www.sgi.com/tech/stl/concepts/allocator.html Allocator]]
|
||||
[def __std_allocators__ [@http://www.sgi.com/tech/stl/concepts/allocator.html Allocators]]
|
||||
|
||||
[def __boost__ptr_map__ [@http://www.boost.org/libs/ptr_container/doc/ptr_map.html `__boost__ptr_map__`]]
|
||||
|
||||
[def __boost__factory__ `boost::factory`]
|
||||
[def __boost__value_factory__ `boost::value_factory`]
|
||||
|
||||
[def __factory__ `factory`]
|
||||
[def __value_factory__ `value_factory`]
|
||||
|
||||
|
||||
[section Brief Description]
|
||||
|
||||
The template __boost__factory__ lets you encapsulate a `new` expression
|
||||
as a function object, __boost__value_factory__ encapsulates a constructor
|
||||
invocation without `new`.
|
||||
|
||||
__boost__factory__<T*>()(arg1,arg2,arg3)
|
||||
// same as new T(arg1,arg2,arg3)
|
||||
|
||||
__boost__value_factory__<T>()(arg1,arg2,arg3)
|
||||
// same as T(arg1,arg2,arg3)
|
||||
|
||||
For technical reasons the arguments to the function objects have to be
|
||||
LValues. A factory that also accepts RValues can be composed using the
|
||||
__boost__forward_adapter__ or __boost__bind__.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Background]
|
||||
|
||||
In traditional Object Oriented Programming a Factory is an object implementing
|
||||
an interface of one or more methods that construct objects conforming to known
|
||||
interfaces.
|
||||
|
||||
// assuming a_concrete_class and another_concrete_class are derived
|
||||
// from an_abstract_class
|
||||
|
||||
class a_factory
|
||||
{
|
||||
public:
|
||||
virtual an_abstract_class* create() const = 0;
|
||||
virtual ~a_factory() { }
|
||||
};
|
||||
|
||||
class a_concrete_factory : public a_factory
|
||||
{
|
||||
public:
|
||||
virtual an_abstract_class* create() const
|
||||
{
|
||||
return new a_concrete_class();
|
||||
}
|
||||
};
|
||||
|
||||
class another_concrete_factory : public a_factory
|
||||
{
|
||||
public:
|
||||
virtual an_abstract_class* create() const
|
||||
{
|
||||
return new another_concrete_class();
|
||||
}
|
||||
};
|
||||
|
||||
// [...]
|
||||
|
||||
int main()
|
||||
{
|
||||
__boost__ptr_map__<__std__string__,a_factory> factories;
|
||||
|
||||
// [...]
|
||||
|
||||
factories.insert("a_name",std::auto_ptr<a_factory>(
|
||||
new a_concrete_factory));
|
||||
factories.insert("another_name",std::auto_ptr<a_factory>(
|
||||
new another_concrete_factory));
|
||||
|
||||
// [...]
|
||||
|
||||
std::auto_ptr<an_abstract_factory> x = factories[some_name]->create();
|
||||
|
||||
// [...]
|
||||
}
|
||||
|
||||
This approach has several drawbacks. The most obvious one is that there is
|
||||
lots of boilerplate code. In other words there is too much code to express
|
||||
a rather simple intention. We could use templates to get rid of some of it
|
||||
but the approach remains inflexible:
|
||||
|
||||
o We may want a factory that takes some arguments that are forwarded to
|
||||
the constructor,
|
||||
o we will probably want to use smart pointers,
|
||||
o we may want several member functions to create different kinds of
|
||||
objects,
|
||||
o we might not necessarily need a polymorphic base class for the objects,
|
||||
o as we will see, we do not need a factory base class at all,
|
||||
o we might want to just call the constructor - without `new` to create
|
||||
an object on the stack, and
|
||||
o finally we might want to use customized memory management.
|
||||
|
||||
Experience has shown that using function objects and generic Boost components
|
||||
for their composition, Design Patterns that describe callback mechasisms
|
||||
(typically requiring a high percentage of boilerplate code with pure Object
|
||||
Oriented methodology) become implementable with just few code lines and without
|
||||
extra classes.
|
||||
|
||||
Factories are callback mechanisms for constructors, so we provide two class
|
||||
templates, __boost__value_factory__ and __boost__factory__, that encasulate
|
||||
object construction via direct application of the constructor and the `new`
|
||||
operator, respectively.
|
||||
|
||||
We let the function objects forward their arguments to the construction
|
||||
expressions they encapsulate. Overthis __boost__factory__ optionally allows
|
||||
the use of smart pointers and __std_allocators__.
|
||||
|
||||
Compile-time polymorphism can be used where appropriate,
|
||||
|
||||
template< class T >
|
||||
void do_something()
|
||||
{
|
||||
// [...]
|
||||
T x = T(a,b);
|
||||
|
||||
// for conceptually similar objects x we neither need virtual
|
||||
// functions nor a common base class in this context.
|
||||
// [...]
|
||||
}
|
||||
|
||||
Now, to allow inhomogenous signaturs for the constructors of the types passed
|
||||
in for `T` we can use __value_factory__ and __boost__bind__ to normalize between
|
||||
them.
|
||||
|
||||
template< class ValueFactory >
|
||||
void do_something(ValueFactory make_obj = ValueFactory())
|
||||
{
|
||||
// [...]
|
||||
typename ValueFactory::result_type x = make_obj(a,b);
|
||||
|
||||
// for conceptually similar objects x we neither need virtual
|
||||
// functions nor a common base class in this context.
|
||||
// [...]
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// [...]
|
||||
|
||||
do_something(__boost__value_factory__<X>());
|
||||
do_something(boost::bind(__boost__value_factory__<Y>(),_1,5,_2));
|
||||
// construct X(a,b) and Y(a,5,b), respectively.
|
||||
|
||||
// [...]
|
||||
}
|
||||
|
||||
Maybe we want our objects to outlive the function's scope, in this case we
|
||||
have to use dynamic allocation;
|
||||
|
||||
template< class Factory >
|
||||
whatever do_something(Factory new_obj = Factory())
|
||||
{
|
||||
typename Factory::result_type ptr = new_obj(a,b);
|
||||
|
||||
// again, no common base class or virtual functions needed,
|
||||
// we could enforce a polymorphic base by writing e.g.
|
||||
// boost::shared_ptr<base>
|
||||
// instead of
|
||||
// typename Factory::result_type
|
||||
// above.
|
||||
// Note that we are also free to have the type erasure happen
|
||||
// somewhere else (e.g. in the constructor of this function's
|
||||
// result type).
|
||||
|
||||
// [...]
|
||||
}
|
||||
|
||||
// [... call do_something like above but with __factory__ instead
|
||||
// of __value_factory__]
|
||||
|
||||
Although we might have created polymorphic objects in the previous example,
|
||||
we have used compile time polymorphism for the factory. If we want to erase
|
||||
the type of the factory and thus allow polymorphism at run time, we can
|
||||
use __boost_function__ to do so. The first example can be rewritten as
|
||||
follows.
|
||||
|
||||
typedef boost::function< an_abstract_class*() > a_factory;
|
||||
|
||||
// [...]
|
||||
|
||||
int main()
|
||||
{
|
||||
__std__map__<__std__string__,a_factory> factories;
|
||||
|
||||
// [...]
|
||||
|
||||
factories["a_name"] = __boost__factory__<a_concrete_class*>();
|
||||
factories["another_name"] =
|
||||
__boost__factory__<another_concrete_class*>();
|
||||
|
||||
// [...]
|
||||
}
|
||||
|
||||
Of course we can just as easy create factories that take arguments and/or
|
||||
return __smart_pointers__.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:reference Reference]
|
||||
|
||||
|
||||
[section value_factory]
|
||||
|
||||
[heading Description]
|
||||
|
||||
Function object template that invokes the constructor of the type `T`.
|
||||
|
||||
[heading Header]
|
||||
#include <boost/functional/value_factory.hpp>
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< typename T >
|
||||
class value_factory;
|
||||
}
|
||||
|
||||
[variablelist Notation
|
||||
[[`T`] [an arbitrary type with at least one public constructor]]
|
||||
[[`a0`...`aN`] [argument LValues to a constructor of `T`]]
|
||||
[[`F`] [the type `value_factory<F>`]]
|
||||
[[`f`] [an instance object of `F`]]
|
||||
]
|
||||
|
||||
[heading Expression Semantics]
|
||||
|
||||
[table
|
||||
[[Expression] [Semantics]]
|
||||
[[`F()`] [creates an object of type `F`.]]
|
||||
[[`F(f)`] [creates an object of type `F`.]]
|
||||
[[`f(a0`...`aN)`] [returns `T(a0`...`aN)`.]]
|
||||
[[`F::result_type`] [is the type `T`.]]
|
||||
]
|
||||
|
||||
[heading Limits]
|
||||
|
||||
The macro BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY can be defined to set the
|
||||
maximum arity. It defaults to 10.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section factory]
|
||||
|
||||
[heading Description]
|
||||
|
||||
Function object template that dynamically constructs a pointee object for
|
||||
the type of pointer given as template argument. Smart pointers may be used
|
||||
for the template argument, given that `boost::pointee<Pointer>::type` yields
|
||||
the pointee type.
|
||||
|
||||
If an __allocator__ is given, it is used for memory allocation and the
|
||||
placement form of the `new` operator is used to construct the object.
|
||||
A function object that calls the destructor and deallocates the memory
|
||||
with a copy of the Allocator is used for the second constructor argument
|
||||
of `Pointer` (thus it must be a __smart_pointer__ that provides a suitable
|
||||
constructor, such as __boost__shared_ptr__).
|
||||
|
||||
If a third template argument is `factory_passes_alloc_to_smart_pointer`,
|
||||
the allocator itself is used for the third constructor argument of `Pointer`
|
||||
(__boost__shared_ptr__ then uses the allocator to manage the memory of its
|
||||
seperately allocated reference counter).
|
||||
|
||||
[heading Header]
|
||||
#include <boost/functional/factory.hpp>
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
enum factory_alloc_propagation
|
||||
{
|
||||
factory_alloc_for_pointee_and_deleter,
|
||||
factory_passes_alloc_to_smart_pointer
|
||||
};
|
||||
|
||||
template< typename Pointer,
|
||||
class Allocator = boost::none_t,
|
||||
factory_alloc_propagation AllocProp =
|
||||
factory_alloc_for_pointee_and_deleter >
|
||||
class factory;
|
||||
}
|
||||
|
||||
[variablelist Notation
|
||||
[[`T`] [an arbitrary type with at least one public constructor]]
|
||||
[[`P`] [pointer or smart pointer to `T`]]
|
||||
[[`a0`...`aN`] [argument LValues to a constructor of `T`]]
|
||||
[[`F`] [the type `factory<P>`]]
|
||||
[[`f`] [an instance object of `F`]]
|
||||
]
|
||||
|
||||
[heading Expression Semantics]
|
||||
|
||||
[table
|
||||
[[Expression] [Semantics]]
|
||||
[[`F()`] [creates an object of type `F`.]]
|
||||
[[`F(f)`] [creates an object of type `F`.]]
|
||||
[[`f(a0`...`aN)`] [dynamically creates an object of type `T` using
|
||||
`a0`...`aN` as arguments for the constructor invocation.]]
|
||||
[[`F::result_type`] [is the type `P` with top-level cv-qualifiers removed.]]
|
||||
]
|
||||
|
||||
[heading Limits]
|
||||
|
||||
The macro BOOST_FUNCTIONAL_FACTORY_MAX_ARITY can be defined to set the
|
||||
maximum arity. It defaults to 10.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Acknowledgements]
|
||||
|
||||
Eric Niebler requested a function to invoke a type's constructor (with the
|
||||
arguments supplied as a Tuple) as a Fusion feature. These Factory utilities are
|
||||
a factored-out generalization of this idea.
|
||||
|
||||
Dave Abrahams suggested Smart Pointer support for exception safety, providing
|
||||
useful hints for the implementation.
|
||||
|
||||
Joel de Guzman's documentation style was copied from Fusion.
|
||||
|
||||
Further, I want to thank Peter Dimov for sharing his insights on language
|
||||
details and their evolution.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section References]
|
||||
|
||||
# [@http://en.wikipedia.org/wiki/Design_Patterns Design Patterns],
|
||||
Gamma et al. - Addison Wesley Publishing, 1995
|
||||
|
||||
# [@http://www.sgi.com/tech/stl/ Standard Template Library Programmer's Guide],
|
||||
Hewlett-Packard Company, 1994
|
||||
|
||||
# [@http://www.boost.org/libs/bind/bind.html Boost.Bind],
|
||||
Peter Dimov, 2001-2005
|
||||
|
||||
# [@http://www.boost.org/doc/html/function.html Boost.Function],
|
||||
Douglas Gregor, 2001-2004
|
||||
|
||||
[endsect]
|
||||
|
||||
|
528
factory/doc/html/boostbook.css
Normal file
528
factory/doc/html/boostbook.css
Normal file
@@ -0,0 +1,528 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2004 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
Body defaults
|
||||
=============================================================================*/
|
||||
|
||||
body
|
||||
{
|
||||
margin: 1em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Paragraphs
|
||||
=============================================================================*/
|
||||
|
||||
p
|
||||
{
|
||||
text-align: left;
|
||||
font-size: 10pt;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Program listings
|
||||
=============================================================================*/
|
||||
|
||||
/* Code on paragraphs */
|
||||
p tt.computeroutput
|
||||
{
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
pre.synopsis
|
||||
{
|
||||
font-size: 90%;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
font-size: 9pt;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
/* Program listings in tables don't get borders */
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
margin: 0pc 0pc 0pc 0pc;
|
||||
padding: 0pc 0pc 0pc 0pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Headings
|
||||
=============================================================================*/
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
text-align: left;
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 { font: 140% }
|
||||
h2 { font: bold 140% }
|
||||
h3 { font: bold 130% }
|
||||
h4 { font: bold 120% }
|
||||
h5 { font: italic 110% }
|
||||
h6 { font: italic 100% }
|
||||
|
||||
/* Top page titles */
|
||||
title,
|
||||
h1.title,
|
||||
h2.title
|
||||
h3.title,
|
||||
h4.title,
|
||||
h5.title,
|
||||
h6.title,
|
||||
.refentrytitle
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-bottom: 1pc;
|
||||
}
|
||||
|
||||
h1.title { font-size: 140% }
|
||||
h2.title { font-size: 140% }
|
||||
h3.title { font-size: 130% }
|
||||
h4.title { font-size: 120% }
|
||||
h5.title { font-size: 110% }
|
||||
h6.title { font-size: 100% }
|
||||
|
||||
.section h1
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
.section h2 { font-size: 140% }
|
||||
.section h3 { font-size: 130% }
|
||||
.section h4 { font-size: 120% }
|
||||
.section h5 { font-size: 110% }
|
||||
.section h6 { font-size: 100% }
|
||||
|
||||
/* Code on titles */
|
||||
h1 tt.computeroutput { font-size: 140% }
|
||||
h2 tt.computeroutput { font-size: 140% }
|
||||
h3 tt.computeroutput { font-size: 130% }
|
||||
h4 tt.computeroutput { font-size: 120% }
|
||||
h5 tt.computeroutput { font-size: 110% }
|
||||
h6 tt.computeroutput { font-size: 100% }
|
||||
|
||||
/*=============================================================================
|
||||
Author
|
||||
=============================================================================*/
|
||||
|
||||
h3.author
|
||||
{
|
||||
font-size: 100%
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Lists
|
||||
=============================================================================*/
|
||||
|
||||
li
|
||||
{
|
||||
font-size: 10pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Unordered lists */
|
||||
ul
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Ordered lists */
|
||||
ol
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Links
|
||||
=============================================================================*/
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Spirit style navigation
|
||||
=============================================================================*/
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.spirit-nav a
|
||||
{
|
||||
color: white;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.spirit-nav img
|
||||
{
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Table of contents
|
||||
=============================================================================*/
|
||||
|
||||
.toc
|
||||
{
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.1pc 1pc 0.1pc 1pc;
|
||||
font-size: 80%;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.boost-toc
|
||||
{
|
||||
float: right;
|
||||
padding: 0.5pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Tables
|
||||
=============================================================================*/
|
||||
|
||||
.table-title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-left: 4%;
|
||||
padding-right: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
width: 92%;
|
||||
margin-left: 4%;
|
||||
margin-right: 4%;
|
||||
}
|
||||
|
||||
div.informaltable table,
|
||||
div.table table
|
||||
{
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Table Cells */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
padding: 0.5em;
|
||||
text-align: left;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
border: 1pt solid white;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Blurbs
|
||||
=============================================================================*/
|
||||
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
div.sidebar
|
||||
{
|
||||
font-size: 9pt; /* A little bit smaller than the main text */
|
||||
line-height: 1.2;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.0pc 0.5pc;
|
||||
}
|
||||
|
||||
div.sidebar img
|
||||
{
|
||||
padding: 1pt;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Callouts
|
||||
=============================================================================*/
|
||||
.line_callout_bug img
|
||||
{
|
||||
float: left;
|
||||
position:relative;
|
||||
left: 4px;
|
||||
top: -12px;
|
||||
clear: left;
|
||||
margin-left:-22px;
|
||||
}
|
||||
|
||||
.callout_bug img
|
||||
{
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Variable Lists
|
||||
=============================================================================*/
|
||||
|
||||
/* Make the terms in definition lists bold */
|
||||
div.variablelist dl dt,
|
||||
span.term
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td
|
||||
{
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 0em 2em 0em 0em;
|
||||
font-size: 10pt;
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.variablelist dl dt
|
||||
{
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
div.variablelist dl dd
|
||||
{
|
||||
margin: 0em 0em 0.5em 2em;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td p,
|
||||
div.variablelist dl dd p
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Misc
|
||||
=============================================================================*/
|
||||
|
||||
/* Title of books and articles in bibliographies */
|
||||
span.title
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
span.underline
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.strikethrough
|
||||
{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
div div.legalnotice p
|
||||
{
|
||||
text-align: left
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Colors
|
||||
=============================================================================*/
|
||||
|
||||
@media screen
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: #005a9c;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: #9c5a9c;
|
||||
}
|
||||
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
|
||||
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
|
||||
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* Syntax Highlighting */
|
||||
.keyword { color: #0000AA; }
|
||||
.identifier { color: #000000; }
|
||||
.special { color: #707070; }
|
||||
.preprocessor { color: #402080; }
|
||||
.char { color: teal; }
|
||||
.comment { color: #800000; }
|
||||
.string { color: teal; }
|
||||
.number { color: teal; }
|
||||
.white_bkd { background-color: #FFFFFF; }
|
||||
.dk_grey_bkd { background-color: #999999; }
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
.copyright
|
||||
{
|
||||
color: #666666;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div div.legalnotice p
|
||||
{
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Blurbs */
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
div.sidebar
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
background-color: #F0F0F0;
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
color: #00A000;
|
||||
}
|
||||
}
|
||||
|
||||
@media print
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
border: 1px solid gray;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
598
factory/doc/html/index.html
Normal file
598
factory/doc/html/index.html
Normal file
@@ -0,0 +1,598 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter<EFBFBD>1.<2E>Boost.Functional/Factory 1.0</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.68.1">
|
||||
<link rel="start" href="index.html" title="Chapter<65>1.<2E>Boost.Functional/Factory 1.0">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
<div class="chapter" lang="en">
|
||||
<div class="titlepage"><div>
|
||||
<div><h2 class="title">
|
||||
<a name="boost_functional_factory"></a>Chapter<EFBFBD>1.<2E>Boost.Functional/Factory 1.0</h2></div>
|
||||
<div><div class="author"><h3 class="author">
|
||||
<span class="firstname">Tobias</span> <span class="surname">Schwinger</span>
|
||||
</h3></div></div>
|
||||
<div><p class="copyright">Copyright <20> 2007, 2008 Tobias Schwinger</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id934161"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.brief_description">Brief Description</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.background">Background</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.reference"> Reference</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.acknowledgements">Acknowledgements</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.references">References</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_factory.brief_description"></a><a href="index.html#boost_functional_factory.brief_description" title="Brief Description">Brief Description</a></h2></div></div></div>
|
||||
<p>
|
||||
The template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code> lets you encapsulate a <code class="computeroutput"><span class="keyword">new</span></code> expression as a function object, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">value_factory</span></code>
|
||||
encapsulates a constructor invocation without <code class="computeroutput"><span class="keyword">new</span></code>.
|
||||
</p>
|
||||
<pre class="programlisting"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code><span class="special"><</span><span class="identifier">T</span><span class="special">*>()(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">,</span><span class="identifier">arg3</span><span class="special">)</span>
|
||||
<span class="comment">// same as new T(arg1,arg2,arg3)
|
||||
</span>
|
||||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">value_factory</span></code><span class="special"><</span><span class="identifier">T</span><span class="special">>()(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier">arg2</span><span class="special">,</span><span class="identifier">arg3</span><span class="special">)</span>
|
||||
<span class="comment">// same as T(arg1,arg2,arg3)
|
||||
</span></pre>
|
||||
<p>
|
||||
For technical reasons the arguments to the function objects have to be LValues.
|
||||
A factory that also accepts RValues can be composed using the <a href="http://www.boost.org/libs/functional/forward/doc/index.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">forward_adapter</span></code></a>
|
||||
or <a href="http://www.boost.org/libs/bind/bind.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span></code></a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_factory.background"></a><a href="index.html#boost_functional_factory.background" title="Background">Background</a></h2></div></div></div>
|
||||
<p>
|
||||
In traditional Object Oriented Programming a Factory is an object implementing
|
||||
an interface of one or more methods that construct objects conforming to known
|
||||
interfaces.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="comment">// assuming a_concrete_class and another_concrete_class are derived
|
||||
</span><span class="comment">// from an_abstract_class
|
||||
</span>
|
||||
<span class="keyword">class</span> <span class="identifier">a_factory</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="keyword">virtual</span> <span class="identifier">an_abstract_class</span><span class="special">*</span> <span class="identifier">create</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
||||
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">a_factory</span><span class="special">()</span> <span class="special">{</span> <span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">class</span> <span class="identifier">a_concrete_factory</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">a_factory</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="keyword">virtual</span> <span class="identifier">an_abstract_class</span><span class="special">*</span> <span class="identifier">create</span><span class="special">()</span> <span class="keyword">const</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">a_concrete_class</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">class</span> <span class="identifier">another_concrete_factory</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">a_factory</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="keyword">virtual</span> <span class="identifier">an_abstract_class</span><span class="special">*</span> <span class="identifier">create</span><span class="special">()</span> <span class="keyword">const</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">another_concrete_class</span><span class="special">();</span>
|
||||
<span class="special">}</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<a href="http://www.boost.org/libs/ptr_container/doc/ptr_map.html" target="_top"><code class="computeroutput"><span class="identifier">__boost__ptr_map__</span></code></a><span class="special"><</span><a href="http://www.sgi.com/tech/stl/string.html" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code></a><span class="special">,</span><span class="identifier">a_factory</span><span class="special">></span> <span class="identifier">factories</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="identifier">factories</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="string">"a_name"</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">auto_ptr</span><span class="special"><</span><span class="identifier">a_factory</span><span class="special">>(</span>
|
||||
<span class="keyword">new</span> <span class="identifier">a_concrete_factory</span><span class="special">));</span>
|
||||
<span class="identifier">factories</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="string">"another_name"</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">auto_ptr</span><span class="special"><</span><span class="identifier">a_factory</span><span class="special">>(</span>
|
||||
<span class="keyword">new</span> <span class="identifier">another_concrete_factory</span><span class="special">));</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">auto_ptr</span><span class="special"><</span><span class="identifier">an_abstract_factory</span><span class="special">></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">factories</span><span class="special">[</span><span class="identifier">some_name</span><span class="special">]-></span><span class="identifier">create</span><span class="special">();</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
This approach has several drawbacks. The most obvious one is that there is
|
||||
lots of boilerplate code. In other words there is too much code to express
|
||||
a rather simple intention. We could use templates to get rid of some of it
|
||||
but the approach remains inflexible:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">o</span> <span class="identifier">We</span> <span class="identifier">may</span> <span class="identifier">want</span> <span class="identifier">a</span> <span class="identifier">factory</span> <span class="identifier">that</span> <span class="identifier">takes</span> <span class="identifier">some</span> <span class="identifier">arguments</span> <span class="identifier">that</span> <span class="identifier">are</span> <span class="identifier">forwarded</span> <span class="identifier">to</span>
|
||||
<span class="identifier">the</span> <span class="identifier">constructor</span><span class="special">,</span>
|
||||
<span class="identifier">o</span> <span class="identifier">we</span> <span class="identifier">will</span> <span class="identifier">probably</span> <span class="identifier">want</span> <span class="identifier">to</span> <span class="identifier">use</span> <span class="identifier">smart</span> <span class="identifier">pointers</span><span class="special">,</span>
|
||||
<span class="identifier">o</span> <span class="identifier">we</span> <span class="identifier">may</span> <span class="identifier">want</span> <span class="identifier">several</span> <span class="identifier">member</span> <span class="identifier">functions</span> <span class="identifier">to</span> <span class="identifier">create</span> <span class="identifier">different</span> <span class="identifier">kinds</span> <span class="identifier">of</span>
|
||||
<span class="identifier">objects</span><span class="special">,</span>
|
||||
<span class="identifier">o</span> <span class="identifier">we</span> <span class="identifier">might</span> <span class="keyword">not</span> <span class="identifier">necessarily</span> <span class="identifier">need</span> <span class="identifier">a</span> <span class="identifier">polymorphic</span> <span class="identifier">base</span> <span class="keyword">class</span> <span class="keyword">for</span> <span class="identifier">the</span> <span class="identifier">objects</span><span class="special">,</span>
|
||||
<span class="identifier">o</span> <span class="identifier">as</span> <span class="identifier">we</span> <span class="identifier">will</span> <span class="identifier">see</span><span class="special">,</span> <span class="identifier">we</span> <span class="keyword">do</span> <span class="keyword">not</span> <span class="identifier">need</span> <span class="identifier">a</span> <span class="identifier">factory</span> <span class="identifier">base</span> <span class="keyword">class</span> <span class="identifier">at</span> <span class="identifier">all</span><span class="special">,</span>
|
||||
<span class="identifier">o</span> <span class="identifier">we</span> <span class="identifier">might</span> <span class="identifier">want</span> <span class="identifier">to</span> <span class="identifier">just</span> <span class="identifier">call</span> <span class="identifier">the</span> <span class="identifier">constructor</span> <span class="special">-</span> <span class="identifier">without</span> #<span class="keyword">new</span># <span class="identifier">to</span> <span class="identifier">create</span>
|
||||
<span class="identifier">an</span> <span class="identifier">object</span> <span class="identifier">on</span> <span class="identifier">the</span> <span class="identifier">stack</span><span class="special">,</span> <span class="keyword">and</span>
|
||||
<span class="identifier">o</span> <span class="identifier">finally</span> <span class="identifier">we</span> <span class="identifier">might</span> <span class="identifier">want</span> <span class="identifier">to</span> <span class="identifier">use</span> <span class="identifier">customized</span> <span class="identifier">memory</span> <span class="identifier">management</span><span class="special">.</span>
|
||||
</pre>
|
||||
<p>
|
||||
Experience has shown that using function objects and generic Boost components
|
||||
for their composition, Design Patterns that describe callback mechasisms (typically
|
||||
requiring a high percentage of boilerplate code with pure Object Oriented methodology)
|
||||
become implementable with just few code lines and without extra classes.
|
||||
</p>
|
||||
<p>
|
||||
Factories are callback mechanisms for constructors, so we provide two class
|
||||
templates, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">value_factory</span></code> and <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code>,
|
||||
that encasulate object construction via direct application of the constructor
|
||||
and the <code class="computeroutput"><span class="keyword">new</span></code> operator, respectively.
|
||||
</p>
|
||||
<p>
|
||||
We let the function objects forward their arguments to the construction expressions
|
||||
they encapsulate. Overthis <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code>
|
||||
optionally allows the use of smart pointers and <a href="http://www.sgi.com/tech/stl/concepts/allocator.html" target="_top">Allocators</a>.
|
||||
</p>
|
||||
<p>
|
||||
Compile-time polymorphism can be used where appropriate,
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">T</span> <span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="identifier">do_something</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// [...]
|
||||
</span> <span class="identifier">T</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">T</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">);</span>
|
||||
|
||||
<span class="comment">// for conceptually similar objects x we neither need virtual
|
||||
</span> <span class="comment">// functions nor a common base class in this context.
|
||||
</span> <span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now, to allow inhomogenous signaturs for the constructors of the types passed
|
||||
in for <code class="computeroutput"><span class="identifier">T</span></code> we can use <code class="computeroutput"><span class="identifier">value_factory</span></code> and <a href="http://www.boost.org/libs/bind/bind.html" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span></code></a>
|
||||
to normalize between them.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">ValueFactory</span> <span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="identifier">do_something</span><span class="special">(</span><span class="identifier">ValueFactory</span> <span class="identifier">make_obj</span> <span class="special">=</span> <span class="identifier">ValueFactory</span><span class="special">())</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// [...]
|
||||
</span> <span class="keyword">typename</span> <span class="identifier">ValueFactory</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">make_obj</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">);</span>
|
||||
|
||||
<span class="comment">// for conceptually similar objects x we neither need virtual
|
||||
</span> <span class="comment">// functions nor a common base class in this context.
|
||||
</span> <span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
|
||||
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="identifier">do_something</span><span class="special">(</span><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">value_factory</span></code><span class="special"><</span><span class="identifier">X</span><span class="special">>());</span>
|
||||
<span class="identifier">do_something</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">value_factory</span></code><span class="special"><</span><span class="identifier">Y</span><span class="special">>(),</span><span class="identifier">_1</span><span class="special">,</span><span class="number">5</span><span class="special">,</span><span class="identifier">_2</span><span class="special">));</span>
|
||||
<span class="comment">// construct X(a,b) and Y(a,5,b), respectively.
|
||||
</span>
|
||||
<span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Maybe we want our objects to outlive the function's scope, in this case we
|
||||
have to use dynamic allocation;
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">Factory</span> <span class="special">></span>
|
||||
<span class="identifier">whatever</span> <span class="identifier">do_something</span><span class="special">(</span><span class="identifier">Factory</span> <span class="identifier">new_obj</span> <span class="special">=</span> <span class="identifier">Factory</span><span class="special">())</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">typename</span> <span class="identifier">Factory</span><span class="special">::</span><span class="identifier">result_type</span> <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">new_obj</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span><span class="identifier">b</span><span class="special">);</span>
|
||||
|
||||
<span class="comment">// again, no common base class or virtual functions needed,
|
||||
</span> <span class="comment">// we could enforce a polymorphic base by writing e.g.
|
||||
</span> <span class="comment">// boost::shared_ptr<base>
|
||||
</span> <span class="comment">// instead of
|
||||
</span> <span class="comment">// typename Factory::result_type
|
||||
</span> <span class="comment">// above.
|
||||
</span> <span class="comment">// Note that we are also free to have the type erasure happen
|
||||
</span> <span class="comment">// somewhere else (e.g. in the constructor of this function's
|
||||
</span> <span class="comment">// result type).
|
||||
</span>
|
||||
<span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
|
||||
<span class="comment">// [... call do_something like above but with __factory__ instead
|
||||
</span><span class="comment">// of __value_factory__]
|
||||
</span></pre>
|
||||
<p>
|
||||
Although we might have created polymorphic objects in the previous example,
|
||||
we have used compile time polymorphism for the factory. If we want to erase
|
||||
the type of the factory and thus allow polymorphism at run time, we can use
|
||||
<a href="http://www.boost.org/doc/html/function.html" target="_top">Boost.Function</a>
|
||||
to do so. The first example can be rewritten as follows.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span> <span class="identifier">an_abstract_class</span><span class="special">*()</span> <span class="special">></span> <span class="identifier">a_factory</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<a href="http://www.sgi.com/tech/stl/map.html" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code></a><span class="special"><</span><a href="http://www.sgi.com/tech/stl/string.html" target="_top"><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code></a><span class="special">,</span><span class="identifier">a_factory</span><span class="special">></span> <span class="identifier">factories</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span>
|
||||
<span class="identifier">factories</span><span class="special">[</span><span class="string">"a_name"</span><span class="special">]</span> <span class="special">=</span> <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code><span class="special"><</span><span class="identifier">a_concrete_class</span><span class="special">*>();</span>
|
||||
<span class="identifier">factories</span><span class="special">[</span><span class="string">"another_name"</span><span class="special">]</span> <span class="special">=</span>
|
||||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">factory</span></code><span class="special"><</span><span class="identifier">another_concrete_class</span><span class="special">*>();</span>
|
||||
|
||||
<span class="comment">// [...]
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Of course we can just as easy create factories that take arguments and/or return
|
||||
<a href="http://www.boost.org/libs/smart_ptr/index.html" target="_top">Smart Pointers</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_factory.reference"></a><a href="index.html#boost_functional_factory.reference" title=" Reference"> Reference</a></h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.reference.value_factory">value_factory</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_factory.reference.factory">factory</a></span></dt>
|
||||
</dl></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_functional_factory.reference.value_factory"></a><a href="index.html#boost_functional_factory.reference.value_factory" title="value_factory">value_factory</a></h3></div></div></div>
|
||||
<a name="boost_functional_factory.reference.value_factory.description"></a><h4>
|
||||
<a name="id936876"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.value_factory.description">Description</a>
|
||||
</h4>
|
||||
<p>
|
||||
Function object template that invokes the constructor of the type <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||
</p>
|
||||
<a name="boost_functional_factory.reference.value_factory.header"></a><h4>
|
||||
<a name="id936914"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.value_factory.header">Header</a>
|
||||
</h4>
|
||||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">functional</span><span class="special">/</span><span class="identifier">value_factory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
</pre>
|
||||
<a name="boost_functional_factory.reference.value_factory.synopsis"></a><h4>
|
||||
<a name="id936989"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.value_factory.synopsis">Synopsis</a>
|
||||
</h4>
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T</span> <span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">value_factory</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<div class="variablelist">
|
||||
<p class="title"><b>Notation</b></p>
|
||||
<dl>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">T</span></code></span></dt>
|
||||
<dd><p>
|
||||
an arbitrary type with at least one public constructor
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code></span></dt>
|
||||
<dd><p>
|
||||
argument LValues to a constructor of <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">F</span></code></span></dt>
|
||||
<dd><p>
|
||||
the type <code class="computeroutput"><span class="identifier">value_factory</span><span class="special"><</span><span class="identifier">F</span><span class="special">></span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">f</span></code></span></dt>
|
||||
<dd><p>
|
||||
an instance object of <code class="computeroutput"><span class="identifier">F</span></code>
|
||||
</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<a name="boost_functional_factory.reference.value_factory.expression_semantics"></a><h4>
|
||||
<a name="id937226"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.value_factory.expression_semantics">Expression
|
||||
Semantics</a>
|
||||
</h4>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<p>
|
||||
Expression
|
||||
</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>
|
||||
Semantics
|
||||
</p>
|
||||
</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">()</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an object of type <code class="computeroutput"><span class="identifier">F</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an object of type <code class="computeroutput"><span class="identifier">F</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
returns <code class="computeroutput"><span class="identifier">T</span><span class="special">(</span><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span><span class="special">)</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">::</span><span class="identifier">result_type</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
is the type <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<a name="boost_functional_factory.reference.value_factory.limits"></a><h4>
|
||||
<a name="id937498"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.value_factory.limits">Limits</a>
|
||||
</h4>
|
||||
<p>
|
||||
The macro BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY can be defined to set
|
||||
the maximum arity. It defaults to 10.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_functional_factory.reference.factory"></a><a href="index.html#boost_functional_factory.reference.factory" title="factory">factory</a></h3></div></div></div>
|
||||
<a name="boost_functional_factory.reference.factory.description"></a><h4>
|
||||
<a name="id937545"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.factory.description">Description</a>
|
||||
</h4>
|
||||
<p>
|
||||
Function object template that dynamically constructs a pointee object for
|
||||
the type of pointer given as template argument. Smart pointers may be used
|
||||
for the template argument, given that <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">pointee</span><span class="special"><</span><span class="identifier">Pointer</span><span class="special">>::</span><span class="identifier">type</span></code>
|
||||
yields the pointee type.
|
||||
</p>
|
||||
<p>
|
||||
If an <span class="underline">_allocator</span>_ is given, it is used
|
||||
for memory allocation and the placement form of the <code class="computeroutput"><span class="keyword">new</span></code>
|
||||
operator is used to construct the object. A function object that calls the
|
||||
destructor and deallocates the memory with a copy of the Allocator is used
|
||||
for the second constructor argument of <code class="computeroutput"><span class="identifier">Pointer</span></code>
|
||||
(thus it must be a __smart<span class="underline">pointer</span>_
|
||||
that provides a suitable constructor, such as <a href="http://www.boost.org/libs/smart_ptr/shared_ptr.htm" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span></code></a>).
|
||||
</p>
|
||||
<p>
|
||||
If a third template argument is <code class="computeroutput"><span class="identifier">factory_passes_alloc_to_smart_pointer</span></code>,
|
||||
the allocator itself is used for the third constructor argument of <code class="computeroutput"><span class="identifier">Pointer</span></code> (<a href="http://www.boost.org/libs/smart_ptr/shared_ptr.htm" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span></code></a> then uses the allocator
|
||||
to manage the memory of its seperately allocated reference counter).
|
||||
</p>
|
||||
<a name="boost_functional_factory.reference.factory.header"></a><h4>
|
||||
<a name="id937729"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.factory.header">Header</a>
|
||||
</h4>
|
||||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">functional</span><span class="special">/</span><span class="identifier">factory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
</pre>
|
||||
<a name="boost_functional_factory.reference.factory.synopsis"></a><h4>
|
||||
<a name="id937804"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.factory.synopsis">Synopsis</a>
|
||||
</h4>
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">enum</span> <span class="identifier">factory_alloc_propagation</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">factory_alloc_for_pointee_and_deleter</span><span class="special">,</span>
|
||||
<span class="identifier">factory_passes_alloc_to_smart_pointer</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">Pointer</span><span class="special">,</span>
|
||||
<span class="keyword">class</span> <span class="identifier">Allocator</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">none_t</span><span class="special">,</span>
|
||||
<span class="identifier">factory_alloc_propagation</span> <span class="identifier">AllocProp</span> <span class="special">=</span>
|
||||
<span class="identifier">factory_alloc_for_pointee_and_deleter</span> <span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">factory</span><span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<div class="variablelist">
|
||||
<p class="title"><b>Notation</b></p>
|
||||
<dl>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">T</span></code></span></dt>
|
||||
<dd><p>
|
||||
an arbitrary type with at least one public constructor
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">P</span></code></span></dt>
|
||||
<dd><p>
|
||||
pointer or smart pointer to <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code></span></dt>
|
||||
<dd><p>
|
||||
argument LValues to a constructor of <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">F</span></code></span></dt>
|
||||
<dd><p>
|
||||
the type <code class="computeroutput"><span class="identifier">factory</span><span class="special"><</span><span class="identifier">P</span><span class="special">></span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">f</span></code></span></dt>
|
||||
<dd><p>
|
||||
an instance object of <code class="computeroutput"><span class="identifier">F</span></code>
|
||||
</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<a name="boost_functional_factory.reference.factory.expression_semantics"></a><h4>
|
||||
<a name="id938169"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.factory.expression_semantics">Expression
|
||||
Semantics</a>
|
||||
</h4>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<p>
|
||||
Expression
|
||||
</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>
|
||||
Semantics
|
||||
</p>
|
||||
</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">()</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an object of type <code class="computeroutput"><span class="identifier">F</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an object of type <code class="computeroutput"><span class="identifier">F</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
dynamically creates an object of type <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
using <code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code> as arguments for the constructor
|
||||
invocation.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">F</span><span class="special">::</span><span class="identifier">result_type</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
is the type <code class="computeroutput"><span class="identifier">P</span></code> with
|
||||
top-level cv-qualifiers removed.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<a name="boost_functional_factory.reference.factory.limits"></a><h4>
|
||||
<a name="id938440"></a>
|
||||
<a href="index.html#boost_functional_factory.reference.factory.limits">Limits</a>
|
||||
</h4>
|
||||
<p>
|
||||
The macro BOOST_FUNCTIONAL_FACTORY_MAX_ARITY can be defined to set the maximum
|
||||
arity. It defaults to 10.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_factory.acknowledgements"></a><a href="index.html#boost_functional_factory.acknowledgements" title="Acknowledgements">Acknowledgements</a></h2></div></div></div>
|
||||
<p>
|
||||
Eric Niebler requested a function to invoke a type's constructor (with the
|
||||
arguments supplied as a Tuple) as a Fusion feature. These Factory utilities
|
||||
are a factored-out generalization of this idea.
|
||||
</p>
|
||||
<p>
|
||||
Dave Abrahams suggested Smart Pointer support for exception safety, providing
|
||||
useful hints for the implementation.
|
||||
</p>
|
||||
<p>
|
||||
Joel de Guzman's documentation style was copied from Fusion.
|
||||
</p>
|
||||
<p>
|
||||
Further, I want to thank Peter Dimov for sharing his insights on language details
|
||||
and their evolution.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_factory.references"></a><a href="index.html#boost_functional_factory.references" title="References">References</a></h2></div></div></div>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<a href="http://en.wikipedia.org/wiki/Design_Patterns" target="_top">Design Patterns</a>,
|
||||
Gamma et al. - Addison Wesley Publishing, 1995
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.sgi.com/tech/stl/" target="_top">Standard Template Library Programmer's
|
||||
Guide</a>, Hewlett-Packard Company, 1994
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.boost.org/libs/bind/bind.html" target="_top">Boost.Bind</a>,
|
||||
Peter Dimov, 2001-2005
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.boost.org/doc/html/function.html" target="_top">Boost.Function</a>,
|
||||
Douglas Gregor, 2001-2004
|
||||
</li>
|
||||
</ol></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: November 01, 2008 at 21:44:52 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
15
factory/index.html
Normal file
15
factory/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, click this
|
||||
<a href="doc/html/index.html">link</a> <hr>
|
||||
<p><EFBFBD> Copyright Tobias Schwinger, 2009</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See
|
||||
accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
18
factory/test/Jamfile
Normal file
18
factory/test/Jamfile
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
# (C) Copyright Tobias Schwinger
|
||||
#
|
||||
# Use modification and distribution are subject to the boost Software License,
|
||||
# Version 1.0. (See http:/\/www.boost.org/LICENSE_1_0.txt).
|
||||
|
||||
import testing ;
|
||||
|
||||
project factory-tests
|
||||
;
|
||||
|
||||
test-suite functional/factory
|
||||
:
|
||||
[ run value_factory.cpp ]
|
||||
[ run factory.cpp ]
|
||||
[ run factory_with_allocator.cpp ]
|
||||
;
|
||||
|
36
factory/test/factory.cpp
Normal file
36
factory/test/factory.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
|
||||
Use modification and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
==============================================================================*/
|
||||
|
||||
#include <boost/functional/factory.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class sum
|
||||
{
|
||||
int val_sum;
|
||||
public:
|
||||
sum(int a, int b) : val_sum(a + b) { }
|
||||
|
||||
operator int() const { return this->val_sum; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int one = 1, two = 2;
|
||||
{
|
||||
sum* instance( boost::factory< sum* >()(one,two) );
|
||||
BOOST_TEST(*instance == 3);
|
||||
}
|
||||
{
|
||||
std::auto_ptr<sum> instance( boost::factory< std::auto_ptr<sum> >()(one,two) );
|
||||
BOOST_TEST(*instance == 3);
|
||||
}
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
79
factory/test/factory_with_allocator.cpp
Normal file
79
factory/test/factory_with_allocator.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
|
||||
Use modification and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
==============================================================================*/
|
||||
|
||||
#include <boost/functional/factory.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
using std::size_t;
|
||||
|
||||
class sum
|
||||
{
|
||||
int val_sum;
|
||||
public:
|
||||
sum(int a, int b) : val_sum(a + b) { }
|
||||
|
||||
operator int() const { return this->val_sum; }
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
class counting_allocator : public std::allocator<T>
|
||||
{
|
||||
public:
|
||||
counting_allocator()
|
||||
{ }
|
||||
|
||||
template< typename OtherT >
|
||||
struct rebind { typedef counting_allocator<OtherT> other; };
|
||||
|
||||
template< typename OtherT >
|
||||
counting_allocator(counting_allocator<OtherT> const& that)
|
||||
{ }
|
||||
|
||||
static size_t n_allocated;
|
||||
T* allocate(size_t n, void const* hint = 0l)
|
||||
{
|
||||
n_allocated += 1;
|
||||
return std::allocator<T>::allocate(n,hint);
|
||||
}
|
||||
|
||||
static size_t n_deallocated;
|
||||
void deallocate(T* ptr, size_t n)
|
||||
{
|
||||
n_deallocated += 1;
|
||||
return std::allocator<T>::deallocate(ptr,n);
|
||||
}
|
||||
};
|
||||
template< typename T > size_t counting_allocator<T>::n_allocated = 0;
|
||||
template< typename T > size_t counting_allocator<T>::n_deallocated = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
int one = 1, two = 2;
|
||||
{
|
||||
boost::shared_ptr<sum> instance(
|
||||
boost::factory< boost::shared_ptr<sum>, counting_allocator<void>,
|
||||
boost::factory_alloc_for_pointee_and_deleter >()(one,two) );
|
||||
BOOST_TEST(*instance == 3);
|
||||
}
|
||||
BOOST_TEST(counting_allocator<sum>::n_allocated == 1);
|
||||
BOOST_TEST(counting_allocator<sum>::n_deallocated == 1);
|
||||
{
|
||||
boost::shared_ptr<sum> instance(
|
||||
boost::factory< boost::shared_ptr<sum>, counting_allocator<void>,
|
||||
boost::factory_passes_alloc_to_smart_pointer >()(one,two) );
|
||||
BOOST_TEST(*instance == 3);
|
||||
}
|
||||
BOOST_TEST(counting_allocator<sum>::n_allocated == 2);
|
||||
BOOST_TEST(counting_allocator<sum>::n_deallocated == 2);
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
29
factory/test/value_factory.cpp
Normal file
29
factory/test/value_factory.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
|
||||
Use modification and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
==============================================================================*/
|
||||
|
||||
#include <boost/functional/value_factory.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
class sum
|
||||
{
|
||||
int val_sum;
|
||||
public:
|
||||
sum(int a, int b) : val_sum(a + b) { }
|
||||
operator int() const { return this->val_sum; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
int one = 1, two = 2;
|
||||
{
|
||||
sum instance( boost::value_factory< sum >()(one,two) );
|
||||
BOOST_TEST(instance == 3);
|
||||
}
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
163
include/boost/functional/factory.hpp
Normal file
163
include/boost/functional/factory.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
|
||||
Use modification and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED
|
||||
# ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
# include <new>
|
||||
# include <boost/pointee.hpp>
|
||||
# include <boost/none_t.hpp>
|
||||
# include <boost/get_pointer.hpp>
|
||||
# include <boost/non_type.hpp>
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
# ifndef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 10
|
||||
# elif BOOST_FUNCTIONAL_FACTORY_MAX_ARITY < 3
|
||||
# undef BOOST_FUNCTIONAL_FACTORY_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_FACTORY_MAX_ARITY 3
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
enum factory_alloc_propagation
|
||||
{
|
||||
factory_alloc_for_pointee_and_deleter,
|
||||
factory_passes_alloc_to_smart_pointer
|
||||
};
|
||||
|
||||
template< typename Pointer, class Allocator = boost::none_t,
|
||||
factory_alloc_propagation AP = factory_alloc_for_pointee_and_deleter >
|
||||
class factory;
|
||||
|
||||
//----- ---- --- -- - - - -
|
||||
|
||||
template< typename Pointer, factory_alloc_propagation AP >
|
||||
class factory<Pointer, boost::none_t, AP>
|
||||
{
|
||||
public:
|
||||
typedef typename boost::remove_cv<Pointer>::type result_type;
|
||||
typedef typename boost::pointee<result_type>::type value_type;
|
||||
|
||||
factory()
|
||||
{ }
|
||||
|
||||
# define BOOST_PP_FILENAME_1 <boost/functional/factory.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY)
|
||||
# include BOOST_PP_ITERATE()
|
||||
};
|
||||
|
||||
template< class Pointer, class Allocator, factory_alloc_propagation AP >
|
||||
class factory
|
||||
: private Allocator::template rebind< typename boost::pointee<
|
||||
typename boost::remove_cv<Pointer>::type >::type >::other
|
||||
{
|
||||
public:
|
||||
typedef typename boost::remove_cv<Pointer>::type result_type;
|
||||
typedef typename boost::pointee<result_type>::type value_type;
|
||||
|
||||
typedef typename Allocator::template rebind<value_type>::other
|
||||
allocator_type;
|
||||
|
||||
explicit factory(allocator_type const & a = allocator_type())
|
||||
: allocator_type(a)
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
||||
struct deleter
|
||||
: allocator_type
|
||||
{
|
||||
inline deleter(allocator_type const& that)
|
||||
: allocator_type(that)
|
||||
{ }
|
||||
|
||||
allocator_type& get_allocator() const
|
||||
{
|
||||
return *const_cast<allocator_type*>(
|
||||
static_cast<allocator_type const*>(this));
|
||||
}
|
||||
|
||||
void operator()(value_type* ptr) const
|
||||
{
|
||||
if (!! ptr) ptr->~value_type();
|
||||
const_cast<allocator_type*>(static_cast<allocator_type const*>(
|
||||
this))->deallocate(ptr,1);
|
||||
}
|
||||
};
|
||||
|
||||
inline allocator_type& get_allocator() const
|
||||
{
|
||||
return *const_cast<allocator_type*>(
|
||||
static_cast<allocator_type const*>(this));
|
||||
}
|
||||
|
||||
inline result_type make_pointer(value_type* ptr, boost::non_type<
|
||||
factory_alloc_propagation,factory_passes_alloc_to_smart_pointer>)
|
||||
const
|
||||
{
|
||||
return result_type(ptr,deleter(this->get_allocator()));
|
||||
}
|
||||
inline result_type make_pointer(value_type* ptr, boost::non_type<
|
||||
factory_alloc_propagation,factory_alloc_for_pointee_and_deleter>)
|
||||
const
|
||||
{
|
||||
return result_type(ptr,deleter(this->get_allocator()),
|
||||
this->get_allocator());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
# define BOOST_TMP_MACRO
|
||||
# define BOOST_PP_FILENAME_1 <boost/functional/factory.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_FACTORY_MAX_ARITY)
|
||||
# include BOOST_PP_ITERATE()
|
||||
# undef BOOST_TMP_MACRO
|
||||
};
|
||||
|
||||
template< typename Pointer, class Allocator, factory_alloc_propagation AP >
|
||||
class factory<Pointer&, Allocator, AP>;
|
||||
// forbidden, would create a dangling reference
|
||||
}
|
||||
|
||||
# define BOOST_FUNCTIONAL_FACTORY_HPP_INCLUDED
|
||||
# else // defined(BOOST_PP_IS_ITERATING)
|
||||
# define N BOOST_PP_ITERATION()
|
||||
# if !defined(BOOST_TMP_MACRO)
|
||||
# if N > 0
|
||||
template< BOOST_PP_ENUM_PARAMS(N, typename T) >
|
||||
# endif
|
||||
inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const
|
||||
{
|
||||
return result_type( new value_type(BOOST_PP_ENUM_PARAMS(N,a)) );
|
||||
}
|
||||
# else // defined(BOOST_TMP_MACRO)
|
||||
# if N > 0
|
||||
template< BOOST_PP_ENUM_PARAMS(N, typename T) >
|
||||
# endif
|
||||
inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const
|
||||
{
|
||||
value_type* memory = this->get_allocator().allocate(1);
|
||||
try
|
||||
{
|
||||
return make_pointer(
|
||||
new(memory) value_type(BOOST_PP_ENUM_PARAMS(N,a)),
|
||||
boost::non_type<factory_alloc_propagation,AP>() );
|
||||
}
|
||||
catch (...) { this->get_allocator().deallocate(memory,1); throw; }
|
||||
}
|
||||
# endif
|
||||
# undef N
|
||||
# endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#endif // include guard
|
||||
|
70
include/boost/functional/value_factory.hpp
Normal file
70
include/boost/functional/value_factory.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
|
||||
Use modification and distribution are subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt).
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_VALUE_FACTORY_HPP_INCLUDED
|
||||
# ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
|
||||
# include <new>
|
||||
# include <boost/pointee.hpp>
|
||||
# include <boost/none_t.hpp>
|
||||
# include <boost/get_pointer.hpp>
|
||||
# include <boost/non_type.hpp>
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
# ifndef BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY 10
|
||||
# elif BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY < 3
|
||||
# undef BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY 3
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< typename T >
|
||||
class value_factory;
|
||||
|
||||
//----- ---- --- -- - - - -
|
||||
|
||||
template< typename T >
|
||||
class value_factory
|
||||
{
|
||||
public:
|
||||
typedef T result_type;
|
||||
|
||||
value_factory()
|
||||
{ }
|
||||
|
||||
# define BOOST_PP_FILENAME_1 <boost/functional/value_factory.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY)
|
||||
# include BOOST_PP_ITERATE()
|
||||
};
|
||||
|
||||
template< typename T > class value_factory<T&>;
|
||||
// forbidden, would create a dangling reference
|
||||
}
|
||||
# define BOOST_FUNCTIONAL_VALUE_FACTORY_HPP_INCLUDED
|
||||
# else // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
# if N > 0
|
||||
template< BOOST_PP_ENUM_PARAMS(N, typename T) >
|
||||
# endif
|
||||
inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const
|
||||
{
|
||||
return result_type(BOOST_PP_ENUM_PARAMS(N,a));
|
||||
}
|
||||
# undef N
|
||||
|
||||
# endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#endif // include guard
|
||||
|
Reference in New Issue
Block a user