mirror of
https://github.com/boostorg/functional.git
synced 2025-08-01 21:44:28 +02:00
adds Functional/Forward
[SVN r61597]
This commit is contained in:
19
forward/doc/Jamfile
Normal file
19
forward/doc/Jamfile
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
# (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 forward : forward.qbk ;
|
||||
boostbook standalone : forward
|
||||
:
|
||||
<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
|
||||
;
|
||||
|
316
forward/doc/forward.qbk
Normal file
316
forward/doc/forward.qbk
Normal file
@@ -0,0 +1,316 @@
|
||||
[library Boost.Functional/Forward
|
||||
[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 adapters for generic argument forwarding.]
|
||||
[category higher-order]
|
||||
[category generic]
|
||||
[last-revision $Date: 2008/11/01 19:58:50 $]
|
||||
]
|
||||
|
||||
[def __unspecified__ /unspecified/]
|
||||
[def __boost_ref__ [@http://www.boost.org/doc/html/ref.html Boost.Ref]]
|
||||
[def __boost_result_of__ [@http://www.boost.org/libs/utility/utility.htm#result_of Boost.ResultOf]]
|
||||
[def __boost__result_of__ [@http://www.boost.org/libs/utility/utility.htm#result_of `boost::result_of`]]
|
||||
[def __the_forwarding_problem__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm The Forwarding Problem]]
|
||||
[def __boost_fusion__ [@http://www.boost.org/libs/fusion/doc/html/index.html Boost.Fusion]]
|
||||
|
||||
[section Brief Description]
|
||||
|
||||
`boost::forward_adapter` provides a reusable adapter template for function
|
||||
objects. It forwards RValues as references to const, while leaving LValues
|
||||
as-is.
|
||||
|
||||
struct g // function object that only accept LValues
|
||||
{
|
||||
template< typename T0, typename T1, typename T2 >
|
||||
void operator()(T0 & t0, T1 & t1, T2 & t2) const;
|
||||
|
||||
typedef void result_type;
|
||||
};
|
||||
|
||||
// Adapted version also accepts RValues and forwards
|
||||
// them as references to const, LValues as-is
|
||||
typedef boost::forward_adapter<g> f;
|
||||
|
||||
Another adapter, `boost::lighweight_forward_adapter` allows forwarding with
|
||||
some help from the user accepting and unwrapping reference wrappers (see
|
||||
__boost_ref__) for reference arguments, const qualifying all other arguments.
|
||||
|
||||
The target functions must be compatible with __boost_result_of__, and so are
|
||||
the adapters.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Background]
|
||||
|
||||
Let's suppose we have some function `f` that we can call like this:
|
||||
|
||||
f(123,a_variable);
|
||||
|
||||
Now we want to write another, generic function `g` that can be called the
|
||||
same way and returns some object that calls `f` with the same arguments.
|
||||
|
||||
f(123,a_variable) == g(f,123,a_variable).call_f()
|
||||
|
||||
[heading Why would we want to do it, anyway?]
|
||||
|
||||
Maybe we want to run `f` several times. Or maybe we want to run it within
|
||||
another thread. Maybe we just want to encapsulate the call expression for now,
|
||||
and then use it with other code that allows to compose more complex expressions
|
||||
in order to decompose it with C++ templates and have the compiler generate some
|
||||
machinery that eventually calls `f` at runtime (in other words; apply a
|
||||
technique that is commonly referred to as Expression Templates).
|
||||
|
||||
[heading Now, how do we do it?]
|
||||
|
||||
The bad news is: It's impossible.
|
||||
|
||||
That is so because there is a slight difference between a variable and an
|
||||
expression that evaluates to its value: Given
|
||||
|
||||
int y;
|
||||
int const z = 0;
|
||||
|
||||
and
|
||||
|
||||
template< typename T > void func1(T & x);
|
||||
|
||||
we can call
|
||||
|
||||
func1(y); // x is a reference to a non-const object
|
||||
func1(z); // x is a reference to a const object
|
||||
|
||||
where
|
||||
|
||||
func1(1); // fails to compile.
|
||||
|
||||
This way we can safely have `func1` store its reference argument and the
|
||||
compiler keeps us from storing a reference to an object with temporary lifetime.
|
||||
|
||||
It is important to realize that non-constness and whether an object binds to a
|
||||
non-const reference parameter are two different properties. The latter is the
|
||||
distinction between LValues and RValues. The names stem from the left hand side
|
||||
and the right hand side of assignment expressions, thus LValues are typically
|
||||
the ones you can assign to, and RValues the temporary results from the right
|
||||
hand side expression.
|
||||
|
||||
y = 1+2; // a is LValue, 1+2 is the expression producing the RValue,
|
||||
// 1+2 = a; // usually makes no sense.
|
||||
|
||||
func1(y); // works, because y is an LValue
|
||||
// func1(1+2); // fails to compile, because we only got an RValue.
|
||||
|
||||
If we add const qualification on the parameter, our function also accepts
|
||||
RValues:
|
||||
|
||||
template< typename T > void func2(T const & x);
|
||||
|
||||
// [...] function scope:
|
||||
func2(1); // x is a reference to a const temporary, object,
|
||||
func2(y); // x is a reference to a const object, while y is not const, and
|
||||
func2(z); // x is a reference to a const object, just like z.
|
||||
|
||||
In all cases, the argument `x` in `func2` is a const-qualified LValue.
|
||||
We can use function overloading to identify non-const LValues:
|
||||
|
||||
template< typename T > void func3(T const & x); // #1
|
||||
template< typename T > void func3(T & x); // #2
|
||||
|
||||
// [...] function scope:
|
||||
func3(1); // x is a reference to a const, temporary object in #1,
|
||||
func3(y); // x is a reference to a non-const object in #2, and
|
||||
func3(z); // x is a reference to a const object in #1.
|
||||
|
||||
Note that all arguments `x` in the overloaded function `func3` are LValues.
|
||||
In fact, there is no way to transport RValues into a function as-is in C++98.
|
||||
Also note that we can't distinguish between what used to be a const qualified
|
||||
LValue and an RValue.
|
||||
|
||||
That's as close as we can get to a generic forwarding function `g` as
|
||||
described above by the means of C++ 98. See __the_forwarding_problem__ for a
|
||||
very detailed discussion including solutions that require language changes.
|
||||
|
||||
Now, for actually implementing it, we need 2^N overloads for N parameters
|
||||
(each with and without const qualifier) for each number of arguments
|
||||
(that is 2^(Nmax+1) - 2^Nmin). Right, that means the compile-time complexity
|
||||
is O(2^N), however the factor is low so it works quite well for a reasonable
|
||||
number (< 10) of arguments.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:reference Reference]
|
||||
|
||||
[section forward_adapter]
|
||||
|
||||
[heading Description]
|
||||
|
||||
Function object adapter template whose instances are callable with LValue and
|
||||
RValue arguments. RValue arguments are forwarded as reference-to-const typed
|
||||
LValues.
|
||||
|
||||
An arity can be given as second, numeric non-type template argument to restrict
|
||||
forwarding to a specific arity.
|
||||
If a third, numeric non-type template argument is present, the second and third
|
||||
template argument are treated as minimum and maximum arity, respectively.
|
||||
Specifying an arity can be helpful to improve the readability of diagnostic
|
||||
messages and compile time performance.
|
||||
|
||||
__boost_result_of__ can be used to determine the result types of specific call
|
||||
expressions.
|
||||
|
||||
[heading Header]
|
||||
#include <boost/functional/forward_adapter.hpp>
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< class Function,
|
||||
int Arity_Or_MinArity = __unspecified__, int MaxArity = __unspecified__ >
|
||||
class forward_adapter;
|
||||
}
|
||||
|
||||
[variablelist Notation
|
||||
[[`F`] [a possibly const qualified function object type or reference type thereof]]
|
||||
[[`f`] [an object convertible to `F`]]
|
||||
[[`FA`] [the type `forward_adapter<F>`]]
|
||||
[[`fa`] [an instance object of `FA`, initialized with `f`]]
|
||||
[[`a0`...`aN`] [arguments to `fa`]]
|
||||
]
|
||||
|
||||
The result type of a target function invocation must be
|
||||
|
||||
__boost__result_of__<F*(TA0 [const]&...TAN [const]&])>::type
|
||||
|
||||
where `TA0`...`TAN` denote the argument types of `a0`...`aN`.
|
||||
|
||||
[heading Expression Semantics]
|
||||
|
||||
[table
|
||||
[[Expression] [Semantics]]
|
||||
[[`FA(f)`] [creates an adapter, initializes the target function with `f`.]]
|
||||
[[`FA()`] [creates an adapter, attempts to use `F`'s default constructor.]]
|
||||
[[`fa(a0`...`aN)`] [calls `f` with with arguments `a0`...`aN`.]]
|
||||
]
|
||||
|
||||
[heading Limits]
|
||||
|
||||
The macro BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY can be defined to set the
|
||||
maximum call arity. It defaults to 6.
|
||||
|
||||
[heading Complexity]
|
||||
|
||||
Preprocessing time: O(2^N), where N is the arity limit.
|
||||
Compile time: O(2^N), where N depends on the arity range.
|
||||
Run time: O(0) if the compiler inlines, O(1) otherwise.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section lightweight_forward_adapter]
|
||||
|
||||
[heading Description]
|
||||
|
||||
Function object adapter template whose instances are callable with LValue and
|
||||
RValue arguments. All arguments are forwarded as reference-to-const typed
|
||||
LValues, except for reference wrappers which are unwrapped and may yield
|
||||
non-const LValues.
|
||||
|
||||
An arity can be given as second, numeric non-type template argument to restrict
|
||||
forwarding to a specific arity.
|
||||
If a third, numeric non-type template argument is present, the second and third
|
||||
template argument are treated as minimum and maximum arity, respectively.
|
||||
Specifying an arity can be helpful to improve the readability of diagnostic
|
||||
messages and compile time performance.
|
||||
|
||||
__boost_result_of__ can be used to determine the result types of specific call
|
||||
expressions.
|
||||
|
||||
[heading Header]
|
||||
#include <boost/functional/lightweight_forward_adapter.hpp>
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< class Function,
|
||||
int Arity_Or_MinArity = __unspecified__, int MaxArity = __unspecified__ >
|
||||
struct lightweight_forward_adapter;
|
||||
}
|
||||
|
||||
[variablelist Notation
|
||||
[[`F`] [a possibly const qualified function object type or reference type thereof]]
|
||||
[[`f`] [an object convertible to `F`]]
|
||||
[[`FA`] [the type `lightweight_forward_adapter<F>`]]
|
||||
[[`fa`] [an instance of `FA`, initialized with `f`]]
|
||||
[[`a0`...`aN`] [arguments to `fa`]]
|
||||
]
|
||||
|
||||
The result type of a target function invocation must be
|
||||
|
||||
__boost__result_of__<F*(TA0 [const]&...TAN [const]&])>::type
|
||||
|
||||
where `TA0`...`TAN` denote the argument types of `a0`...`aN`.
|
||||
|
||||
[heading Expression Semantics]
|
||||
|
||||
[table
|
||||
[[Expression] [Semantics]]
|
||||
[[`FA(f)`] [creates an adapter, initializes the target function with `f`.]]
|
||||
[[`FA()`] [creates an adapter, attempts to use `F`'s default constructor.]]
|
||||
[[`fa(a0`...`aN)`] [calls `f` with with const arguments `a0`...`aN`. If `aI` is a
|
||||
reference wrapper it is unwrapped.]]
|
||||
]
|
||||
|
||||
[heading Limits]
|
||||
|
||||
The macro BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY can be defined
|
||||
to set the maximum call arity. It defaults to 10.
|
||||
|
||||
[heading Complexity]
|
||||
|
||||
Preprocessing time: O(N), where N is the arity limit.
|
||||
Compile time: O(N), where N is the effective arity of a call.
|
||||
Run time: O(0) if the compiler inlines, O(1) otherwise.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section Acknowledgements]
|
||||
|
||||
As these utilities are factored out of the __boost_fusion__ functional module,
|
||||
I want to thank Dan Marsden and Joel de Guzman for letting me participate in the
|
||||
development of that great library in the first place.
|
||||
|
||||
Further, I want to credit the authors of the references below, for their
|
||||
in-depth investigation of the problem and the solution implemented here.
|
||||
|
||||
Last but not least I want to thank Vesa Karnoven and Paul Mensonides for the
|
||||
Boost Preprocessor library. Without it, I would have ended up with an external
|
||||
code generator for this one.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[section References]
|
||||
|
||||
# [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm The Forwarding Problem],
|
||||
Peter Dimov, Howard E. Hinnant, David Abrahams, 2002
|
||||
|
||||
# [@http://www.boost.org/libs/utility/utility.htm#result_of Boost.ResultOf],
|
||||
Douglas Gregor, 2004
|
||||
|
||||
# [@http://www.boost.org/doc/html/ref.html Boost.Ref],
|
||||
Jaakko Jarvi, Peter Dimov, Douglas Gregor, David Abrahams, 1999-2002
|
||||
|
||||
[endsect]
|
||||
|
528
forward/doc/html/boostbook.css
Normal file
528
forward/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;
|
||||
}
|
||||
}
|
564
forward/doc/html/index.html
Normal file
564
forward/doc/html/index.html
Normal file
@@ -0,0 +1,564 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter<EFBFBD>1.<2E>Boost.Functional/Forward 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/Forward 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_forward"></a>Chapter<EFBFBD>1.<2E>Boost.Functional/Forward 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_forward.brief_description">Brief Description</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.background">Background</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.reference"> Reference</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.acknowledgements">Acknowledgements</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.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_forward.brief_description"></a><a href="index.html#boost_functional_forward.brief_description" title="Brief Description">Brief Description</a></h2></div></div></div>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">forward_adapter</span></code> provides a reusable adapter
|
||||
template for function objects. It forwards RValues as references to const,
|
||||
while leaving LValues as-is.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">g</span> <span class="comment">// function object that only accept LValues
|
||||
</span><span class="special">{</span>
|
||||
<span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span> <span class="special">></span>
|
||||
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span> <span class="special">&</span> <span class="identifier">t0</span><span class="special">,</span> <span class="identifier">T1</span> <span class="special">&</span> <span class="identifier">t1</span><span class="special">,</span> <span class="identifier">T2</span> <span class="special">&</span> <span class="identifier">t2</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">result_type</span><span class="special">;</span>
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="comment">// Adapted version also accepts RValues and forwards
|
||||
</span><span class="comment">// them as references to const, LValues as-is
|
||||
</span><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">forward_adapter</span><span class="special"><</span><span class="identifier">g</span><span class="special">></span> <span class="identifier">f</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Another adapter, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">lighweight_forward_adapter</span></code> allows forwarding
|
||||
with some help from the user accepting and unwrapping reference wrappers (see
|
||||
<a href="http://www.boost.org/doc/html/ref.html" target="_top">Boost.Ref</a>) for
|
||||
reference arguments, const qualifying all other arguments.
|
||||
</p>
|
||||
<p>
|
||||
The target functions must be compatible with <a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top">Boost.ResultOf</a>,
|
||||
and so are the adapters.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_forward.background"></a><a href="index.html#boost_functional_forward.background" title="Background">Background</a></h2></div></div></div>
|
||||
<p>
|
||||
Let's suppose we have some function <code class="computeroutput"><span class="identifier">f</span></code>
|
||||
that we can call like this:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">f</span><span class="special">(</span><span class="number">123</span><span class="special">,</span><span class="identifier">a_variable</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now we want to write another, generic function <code class="computeroutput"><span class="identifier">g</span></code>
|
||||
that can be called the same way and returns some object that calls <code class="computeroutput"><span class="identifier">f</span></code> with the same arguments.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">f</span><span class="special">(</span><span class="number">123</span><span class="special">,</span><span class="identifier">a_variable</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">g</span><span class="special">(</span><span class="identifier">f</span><span class="special">,</span><span class="number">123</span><span class="special">,</span><span class="identifier">a_variable</span><span class="special">).</span><span class="identifier">call_f</span><span class="special">()</span>
|
||||
</pre>
|
||||
<a name="boost_functional_forward.background.why_would_we_want_to_do_it__anyway_"></a><h3>
|
||||
<a name="id934701"></a>
|
||||
<a href="index.html#boost_functional_forward.background.why_would_we_want_to_do_it__anyway_">Why
|
||||
would we want to do it, anyway?</a>
|
||||
</h3>
|
||||
<p>
|
||||
Maybe we want to run <code class="computeroutput"><span class="identifier">f</span></code> several
|
||||
times. Or maybe we want to run it within another thread. Maybe we just want
|
||||
to encapsulate the call expression for now, and then use it with other code
|
||||
that allows to compose more complex expressions in order to decompose it with
|
||||
C++ templates and have the compiler generate some machinery that eventually
|
||||
calls <code class="computeroutput"><span class="identifier">f</span></code> at runtime (in other
|
||||
words; apply a technique that is commonly referred to as Expression Templates).
|
||||
</p>
|
||||
<a name="boost_functional_forward.background.now__how_do_we_do_it_"></a><h3>
|
||||
<a name="id934755"></a>
|
||||
<a href="index.html#boost_functional_forward.background.now__how_do_we_do_it_">Now,
|
||||
how do we do it?</a>
|
||||
</h3>
|
||||
<p>
|
||||
The bad news is: It's impossible.
|
||||
</p>
|
||||
<p>
|
||||
That is so because there is a slight difference between a variable and an expression
|
||||
that evaluates to its value: Given
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">y</span><span class="special">;</span>
|
||||
<span class="keyword">int</span> <span class="keyword">const</span> <span class="identifier">z</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
and
|
||||
</p>
|
||||
<pre class="programlisting"><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">void</span> <span class="identifier">func1</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
we can call
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">func1</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span> <span class="comment">// x is a reference to a non-const object
|
||||
</span><span class="identifier">func1</span><span class="special">(</span><span class="identifier">z</span><span class="special">);</span> <span class="comment">// x is a reference to a const object
|
||||
</span></pre>
|
||||
<p>
|
||||
where
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">func1</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// fails to compile.
|
||||
</span></pre>
|
||||
<p>
|
||||
This way we can safely have <code class="computeroutput"><span class="identifier">func1</span></code>
|
||||
store its reference argument and the compiler keeps us from storing a reference
|
||||
to an object with temporary lifetime.
|
||||
</p>
|
||||
<p>
|
||||
It is important to realize that non-constness and whether an object binds to
|
||||
a non-const reference parameter are two different properties. The latter is
|
||||
the distinction between LValues and RValues. The names stem from the left hand
|
||||
side and the right hand side of assignment expressions, thus LValues are typically
|
||||
the ones you can assign to, and RValues the temporary results from the right
|
||||
hand side expression.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">y</span> <span class="special">=</span> <span class="number">1</span><span class="special">+</span><span class="number">2</span><span class="special">;</span> <span class="comment">// a is LValue, 1+2 is the expression producing the RValue,
|
||||
</span><span class="comment">// 1+2 = a; // usually makes no sense.
|
||||
</span>
|
||||
<span class="identifier">func1</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span> <span class="comment">// works, because y is an LValue
|
||||
</span><span class="comment">// func1(1+2); // fails to compile, because we only got an RValue.
|
||||
</span></pre>
|
||||
<p>
|
||||
If we add const qualification on the parameter, our function also accepts RValues:
|
||||
</p>
|
||||
<pre class="programlisting"><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">void</span> <span class="identifier">func2</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
|
||||
|
||||
<span class="comment">// [...] function scope:
|
||||
</span><span class="identifier">func2</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// x is a reference to a const temporary, object,
|
||||
</span><span class="identifier">func2</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span> <span class="comment">// x is a reference to a const object, while y is not const, and
|
||||
</span><span class="identifier">func2</span><span class="special">(</span><span class="identifier">z</span><span class="special">);</span> <span class="comment">// x is a reference to a const object, just like z.
|
||||
</span></pre>
|
||||
<p>
|
||||
In all cases, the argument <code class="computeroutput"><span class="identifier">x</span></code>
|
||||
in <code class="computeroutput"><span class="identifier">func2</span></code> is a const-qualified
|
||||
LValue. We can use function overloading to identify non-const LValues:
|
||||
</p>
|
||||
<pre class="programlisting"><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">void</span> <span class="identifier">func3</span><span class="special">(</span><span class="identifier">T</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span> <span class="comment">// #1
|
||||
</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">void</span> <span class="identifier">func3</span><span class="special">(</span><span class="identifier">T</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span> <span class="comment">// #2
|
||||
</span>
|
||||
<span class="comment">// [...] function scope:
|
||||
</span><span class="identifier">func3</span><span class="special">(</span><span class="number">1</span><span class="special">);</span> <span class="comment">// x is a reference to a const, temporary object in #1,
|
||||
</span><span class="identifier">func3</span><span class="special">(</span><span class="identifier">y</span><span class="special">);</span> <span class="comment">// x is a reference to a non-const object in #2, and
|
||||
</span><span class="identifier">func3</span><span class="special">(</span><span class="identifier">z</span><span class="special">);</span> <span class="comment">// x is a reference to a const object in #1.
|
||||
</span></pre>
|
||||
<p>
|
||||
Note that all arguments <code class="computeroutput"><span class="identifier">x</span></code> in
|
||||
the overloaded function <code class="computeroutput"><span class="identifier">func3</span></code>
|
||||
are LValues. In fact, there is no way to transport RValues into a function
|
||||
as-is in C++98. Also note that we can't distinguish between what used to be
|
||||
a const qualified LValue and an RValue.
|
||||
</p>
|
||||
<p>
|
||||
That's as close as we can get to a generic forwarding function <code class="computeroutput"><span class="identifier">g</span></code> as described above by the means of C++
|
||||
98. See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">The
|
||||
Forwarding Problem</a> for a very detailed discussion including solutions
|
||||
that require language changes.
|
||||
</p>
|
||||
<p>
|
||||
Now, for actually implementing it, we need 2^N overloads for N parameters (each
|
||||
with and without const qualifier) for each number of arguments (that is 2^(Nmax+1)
|
||||
- 2^Nmin). Right, that means the compile-time complexity is O(2^N), however
|
||||
the factor is low so it works quite well for a reasonable number (< 10)
|
||||
of arguments.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_forward.reference"></a><a href="index.html#boost_functional_forward.reference" title=" Reference"> Reference</a></h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.reference.forward_adapter">forward_adapter</a></span></dt>
|
||||
<dt><span class="section"><a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter">lightweight_forward_adapter</a></span></dt>
|
||||
</dl></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_functional_forward.reference.forward_adapter"></a><a href="index.html#boost_functional_forward.reference.forward_adapter" title="forward_adapter">forward_adapter</a></h3></div></div></div>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.description"></a><h4>
|
||||
<a name="id935594"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.description">Description</a>
|
||||
</h4>
|
||||
<p>
|
||||
Function object adapter template whose instances are callable with LValue
|
||||
and RValue arguments. RValue arguments are forwarded as reference-to-const
|
||||
typed LValues.
|
||||
</p>
|
||||
<p>
|
||||
An arity can be given as second, numeric non-type template argument to restrict
|
||||
forwarding to a specific arity. If a third, numeric non-type template argument
|
||||
is present, the second and third template argument are treated as minimum
|
||||
and maximum arity, respectively. Specifying an arity can be helpful to improve
|
||||
the readability of diagnostic messages and compile time performance.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top">Boost.ResultOf</a>
|
||||
can be used to determine the result types of specific call expressions.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.header"></a><h4>
|
||||
<a name="id935646"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.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">forward_adapter</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
</pre>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.synopsis"></a><h4>
|
||||
<a name="id935721"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.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">class</span> <span class="identifier">Function</span><span class="special">,</span>
|
||||
<span class="keyword">int</span> <span class="identifier">Arity_Or_MinArity</span> <span class="special">=</span> <span class="emphasis"><em>unspecified</em></span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">MaxArity</span> <span class="special">=</span> <span class="emphasis"><em>unspecified</em></span> <span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">forward_adapter</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">F</span></code></span></dt>
|
||||
<dd><p>
|
||||
a possibly const qualified function object type or reference type thereof
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">f</span></code></span></dt>
|
||||
<dd><p>
|
||||
an object convertible to <code class="computeroutput"><span class="identifier">F</span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">FA</span></code></span></dt>
|
||||
<dd><p>
|
||||
the type <code class="computeroutput"><span class="identifier">forward_adapter</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">fa</span></code></span></dt>
|
||||
<dd><p>
|
||||
an instance object of <code class="computeroutput"><span class="identifier">FA</span></code>,
|
||||
initialized with <code class="computeroutput"><span class="identifier">f</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>
|
||||
arguments to <code class="computeroutput"><span class="identifier">fa</span></code>
|
||||
</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
The result type of a target function invocation must be
|
||||
</p>
|
||||
<pre class="programlisting"><a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">result_of</span></code></a><span class="special"><</span><span class="identifier">F</span><span class="special">*(</span><span class="identifier">TA0</span> <span class="special">[</span><span class="keyword">const</span><span class="special">]&...</span><span class="identifier">TAN</span> <span class="special">[</span><span class="keyword">const</span><span class="special">]&])>::</span><span class="identifier">type</span>
|
||||
</pre>
|
||||
<p>
|
||||
where <code class="computeroutput"><span class="identifier">TA0</span></code>...<code class="computeroutput"><span class="identifier">TAN</span></code> denote the argument types of <code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code>.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.expression_semantics"></a><h4>
|
||||
<a name="id936177"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.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">FA</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an adapter, initializes the target function with <code class="computeroutput"><span class="identifier">f</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">FA</span><span class="special">()</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an adapter, attempts to use <code class="computeroutput"><span class="identifier">F</span></code>'s
|
||||
default constructor.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">fa</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>
|
||||
calls <code class="computeroutput"><span class="identifier">f</span></code> with with
|
||||
arguments <code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.limits"></a><h4>
|
||||
<a name="id936405"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.limits">Limits</a>
|
||||
</h4>
|
||||
<p>
|
||||
The macro BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY can be defined to set
|
||||
the maximum call arity. It defaults to 6.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.forward_adapter.complexity"></a><h4>
|
||||
<a name="id936434"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.forward_adapter.complexity">Complexity</a>
|
||||
</h4>
|
||||
<p>
|
||||
Preprocessing time: O(2^N), where N is the arity limit. Compile time: O(2^N),
|
||||
where N depends on the arity range. Run time: O(0) if the compiler inlines,
|
||||
O(1) otherwise.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter"></a><a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter" title="lightweight_forward_adapter">lightweight_forward_adapter</a></h3></div></div></div>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.description"></a><h4>
|
||||
<a name="id936485"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.description">Description</a>
|
||||
</h4>
|
||||
<p>
|
||||
Function object adapter template whose instances are callable with LValue
|
||||
and RValue arguments. All arguments are forwarded as reference-to-const typed
|
||||
LValues, except for reference wrappers which are unwrapped and may yield
|
||||
non-const LValues.
|
||||
</p>
|
||||
<p>
|
||||
An arity can be given as second, numeric non-type template argument to restrict
|
||||
forwarding to a specific arity. If a third, numeric non-type template argument
|
||||
is present, the second and third template argument are treated as minimum
|
||||
and maximum arity, respectively. Specifying an arity can be helpful to improve
|
||||
the readability of diagnostic messages and compile time performance.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top">Boost.ResultOf</a>
|
||||
can be used to determine the result types of specific call expressions.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.header"></a><h4>
|
||||
<a name="id936540"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.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">lightweight_forward_adapter</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
</pre>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.synopsis"></a><h4>
|
||||
<a name="id936616"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.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">class</span> <span class="identifier">Function</span><span class="special">,</span>
|
||||
<span class="keyword">int</span> <span class="identifier">Arity_Or_MinArity</span> <span class="special">=</span> <span class="emphasis"><em>unspecified</em></span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">MaxArity</span> <span class="special">=</span> <span class="emphasis"><em>unspecified</em></span> <span class="special">></span>
|
||||
<span class="keyword">struct</span> <span class="identifier">lightweight_forward_adapter</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">F</span></code></span></dt>
|
||||
<dd><p>
|
||||
a possibly const qualified function object type or reference type thereof
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">f</span></code></span></dt>
|
||||
<dd><p>
|
||||
an object convertible to <code class="computeroutput"><span class="identifier">F</span></code>
|
||||
</p></dd>
|
||||
<dt><span class="term"><code class="computeroutput"><span class="identifier">FA</span></code></span></dt>
|
||||
<dd><p>
|
||||
the type <code class="computeroutput"><span class="identifier">lightweight_forward_adapter</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">fa</span></code></span></dt>
|
||||
<dd><p>
|
||||
an instance of <code class="computeroutput"><span class="identifier">FA</span></code>, initialized
|
||||
with <code class="computeroutput"><span class="identifier">f</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>
|
||||
arguments to <code class="computeroutput"><span class="identifier">fa</span></code>
|
||||
</p></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
The result type of a target function invocation must be
|
||||
</p>
|
||||
<pre class="programlisting"><a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top"><code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">result_of</span></code></a><span class="special"><</span><span class="identifier">F</span><span class="special">*(</span><span class="identifier">TA0</span> <span class="special">[</span><span class="keyword">const</span><span class="special">]&...</span><span class="identifier">TAN</span> <span class="special">[</span><span class="keyword">const</span><span class="special">]&])>::</span><span class="identifier">type</span>
|
||||
</pre>
|
||||
<p>
|
||||
where <code class="computeroutput"><span class="identifier">TA0</span></code>...<code class="computeroutput"><span class="identifier">TAN</span></code> denote the argument types of <code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code>.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.expression_semantics"></a><h4>
|
||||
<a name="id937073"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.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">FA</span><span class="special">(</span><span class="identifier">f</span><span class="special">)</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an adapter, initializes the target function with <code class="computeroutput"><span class="identifier">f</span></code>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">FA</span><span class="special">()</span></code>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
creates an adapter, attempts to use <code class="computeroutput"><span class="identifier">F</span></code>'s
|
||||
default constructor.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">fa</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>
|
||||
calls <code class="computeroutput"><span class="identifier">f</span></code> with with
|
||||
const arguments <code class="computeroutput"><span class="identifier">a0</span></code>...<code class="computeroutput"><span class="identifier">aN</span></code>. If <code class="computeroutput"><span class="identifier">aI</span></code>
|
||||
is a reference wrapper it is unwrapped.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table></div>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.limits"></a><h4>
|
||||
<a name="id937311"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.limits">Limits</a>
|
||||
</h4>
|
||||
<p>
|
||||
The macro BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY can be defined
|
||||
to set the maximum call arity. It defaults to 10.
|
||||
</p>
|
||||
<a name="boost_functional_forward.reference.lightweight_forward_adapter.complexity"></a><h4>
|
||||
<a name="id937342"></a>
|
||||
<a href="index.html#boost_functional_forward.reference.lightweight_forward_adapter.complexity">Complexity</a>
|
||||
</h4>
|
||||
<p>
|
||||
Preprocessing time: O(N), where N is the arity limit. Compile time: O(N),
|
||||
where N is the effective arity of a call. Run time: O(0) if the compiler
|
||||
inlines, O(1) otherwise.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_forward.acknowledgements"></a><a href="index.html#boost_functional_forward.acknowledgements" title="Acknowledgements">Acknowledgements</a></h2></div></div></div>
|
||||
<p>
|
||||
As these utilities are factored out of the <a href="http://www.boost.org/libs/fusion/doc/html/index.html" target="_top">Boost.Fusion</a>
|
||||
functional module, I want to thank Dan Marsden and Joel de Guzman for letting
|
||||
me participate in the development of that great library in the first place.
|
||||
</p>
|
||||
<p>
|
||||
Further, I want to credit the authors of the references below, for their in-depth
|
||||
investigation of the problem and the solution implemented here.
|
||||
</p>
|
||||
<p>
|
||||
Last but not least I want to thank Vesa Karnoven and Paul Mensonides for the
|
||||
Boost Preprocessor library. Without it, I would have ended up with an external
|
||||
code generator for this one.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_functional_forward.references"></a><a href="index.html#boost_functional_forward.references" title="References">References</a></h2></div></div></div>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">The
|
||||
Forwarding Problem</a>, Peter Dimov, Howard E. Hinnant, David Abrahams,
|
||||
2002
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.boost.org/libs/utility/utility.htm#result_of" target="_top">Boost.ResultOf</a>,
|
||||
Douglas Gregor, 2004
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.boost.org/doc/html/ref.html" target="_top">Boost.Ref</a>, Jaakko
|
||||
Jarvi, Peter Dimov, Douglas Gregor, David Abrahams, 1999-2002
|
||||
</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 19:58:50 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
15
forward/index.html
Normal file
15
forward/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>
|
17
forward/test/Jamfile
Normal file
17
forward/test/Jamfile
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
# (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 forward-tests
|
||||
;
|
||||
|
||||
test-suite functional/forward
|
||||
:
|
||||
[ run forward_adapter.cpp ]
|
||||
[ run lightweight_forward_adapter.cpp ]
|
||||
;
|
||||
|
128
forward/test/forward_adapter.cpp
Normal file
128
forward/test/forward_adapter.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*=============================================================================
|
||||
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/config.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable: 4244) // no conversion warnings, please
|
||||
#endif
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/functional/forward_adapter.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/blank.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
template <class Base = boost::blank>
|
||||
class test_func : public Base
|
||||
{
|
||||
int val;
|
||||
public:
|
||||
test_func(int v) : val(v) { }
|
||||
|
||||
template<class B>
|
||||
test_func(test_func<B> const & that)
|
||||
: val(that.val)
|
||||
{ }
|
||||
|
||||
template<class B> friend class test_func;
|
||||
|
||||
int operator()(int & l, int const & r) const
|
||||
{
|
||||
return l=r+val;
|
||||
}
|
||||
long operator()(int & l, int const & r)
|
||||
{
|
||||
return -(l=r+val);
|
||||
}
|
||||
|
||||
template <typename Sig>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// ensure result_of argument types are what's expected
|
||||
// note: this is *not* how client code should look like
|
||||
template <class Self>
|
||||
struct result< Self const(int&,int const&) > { typedef int type; };
|
||||
|
||||
template <class Self>
|
||||
struct result< Self(int&,int const&) > { typedef long type; };
|
||||
|
||||
template <class Self>
|
||||
struct result< Self(int&,int&) > { typedef char type; };
|
||||
};
|
||||
|
||||
enum { int_, long_, char_ };
|
||||
|
||||
int type_of(int) { return int_; }
|
||||
int type_of(long) { return long_; }
|
||||
int type_of(char) { return char_; }
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using boost::is_same;
|
||||
using boost::result_of;
|
||||
typedef boost::forward_adapter< test_func<> > f;
|
||||
|
||||
// lvalue,rvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(int&, int) >::type, long >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (int&, int) >::type, int >::value ));
|
||||
// lvalue,const lvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(int&, int const &) >::type, long >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (int&, int const &) >::type, int >::value ));
|
||||
// lvalue,lvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(int&, int&) >::type, char >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (int&, int&) >::type, char >::value ));
|
||||
}
|
||||
|
||||
{
|
||||
using boost::noncopyable;
|
||||
using boost::forward_adapter;
|
||||
|
||||
int x = 0;
|
||||
test_func<noncopyable> f(7);
|
||||
forward_adapter< test_func<> > func(f);
|
||||
forward_adapter< test_func<noncopyable> & > func_ref(f);
|
||||
forward_adapter< test_func<noncopyable> & > const func_ref_c(f);
|
||||
forward_adapter< test_func<> const > func_c(f);
|
||||
forward_adapter< test_func<> > const func_c2(f);
|
||||
forward_adapter< test_func<noncopyable> const & > func_c_ref(f);
|
||||
|
||||
BOOST_TEST( type_of( func(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_ref(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_ref_c(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_c(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func_c2(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func_c_ref(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func(x,x) ) == char_ );
|
||||
|
||||
BOOST_TEST( func(x,1) == -8 );
|
||||
BOOST_TEST( func_ref(x,1) == -8 );
|
||||
BOOST_TEST( func_ref_c(x,1) == -8 );
|
||||
BOOST_TEST( func_c(x,1) == 8 );
|
||||
BOOST_TEST( func_c2(x,1) == 8 );
|
||||
BOOST_TEST( func_c_ref(x,1) == 8 );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
128
forward/test/lightweight_forward_adapter.cpp
Normal file
128
forward/test/lightweight_forward_adapter.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*=============================================================================
|
||||
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/config.hpp>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable: 4244) // no conversion warnings, please
|
||||
#endif
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/functional/lightweight_forward_adapter.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/blank.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
template <class Base = boost::blank>
|
||||
class test_func : public Base
|
||||
{
|
||||
int val;
|
||||
public:
|
||||
test_func(int v) : val(v) { }
|
||||
|
||||
template<class B>
|
||||
test_func(test_func<B> const & that)
|
||||
: val(that.val)
|
||||
{ }
|
||||
|
||||
template<class B> friend class test_func;
|
||||
|
||||
int operator()(int & l, int const & r) const
|
||||
{
|
||||
return l=r+val;
|
||||
}
|
||||
long operator()(int & l, int const & r)
|
||||
{
|
||||
return -(l=r+val);
|
||||
}
|
||||
|
||||
template <typename Sig>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
// ensure result_of argument types are what's expected
|
||||
// note: this is *not* how client code should look like
|
||||
template <class Self>
|
||||
struct result< Self const(int&,int const&) > { typedef int type; };
|
||||
|
||||
template <class Self>
|
||||
struct result< Self(int&,int const&) > { typedef long type; };
|
||||
|
||||
template <class Self>
|
||||
struct result< Self(int&,int&) > { typedef char type; };
|
||||
};
|
||||
|
||||
enum { int_, long_, char_ };
|
||||
|
||||
int type_of(int) { return int_; }
|
||||
int type_of(long) { return long_; }
|
||||
int type_of(char) { return char_; }
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using boost::is_same;
|
||||
using boost::result_of;
|
||||
typedef boost::lightweight_forward_adapter< test_func<> > f;
|
||||
typedef boost::reference_wrapper<int> ref;
|
||||
typedef boost::reference_wrapper<int const> cref;
|
||||
|
||||
// lvalue,rvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(ref, int) >::type, long >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (ref, int) >::type, int >::value ));
|
||||
// lvalue,const lvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(ref, cref) >::type, long >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (ref, cref) >::type, int >::value ));
|
||||
// lvalue,lvalue
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f(ref, ref) >::type, char >::value ));
|
||||
BOOST_TEST(( is_same<
|
||||
result_of< f const (ref, ref) >::type, char >::value ));
|
||||
}
|
||||
{
|
||||
using boost::noncopyable;
|
||||
using boost::lightweight_forward_adapter;
|
||||
|
||||
int v = 0; boost::reference_wrapper<int> x(v);
|
||||
test_func<noncopyable> f(7);
|
||||
lightweight_forward_adapter< test_func<> > func(f);
|
||||
lightweight_forward_adapter< test_func<noncopyable> & > func_ref(f);
|
||||
lightweight_forward_adapter< test_func<noncopyable> & > const func_ref_c(f);
|
||||
lightweight_forward_adapter< test_func<> const > func_c(f);
|
||||
lightweight_forward_adapter< test_func<> > const func_c2(f);
|
||||
lightweight_forward_adapter< test_func<noncopyable> const & > func_c_ref(f);
|
||||
|
||||
BOOST_TEST( type_of( func(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_ref(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_ref_c(x,1) ) == long_ );
|
||||
BOOST_TEST( type_of( func_c(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func_c2(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func_c_ref(x,1) ) == int_ );
|
||||
BOOST_TEST( type_of( func(x,x) ) == char_ );
|
||||
|
||||
BOOST_TEST( func(x,1) == -8 );
|
||||
BOOST_TEST( func_ref(x,1) == -8 );
|
||||
BOOST_TEST( func_ref_c(x,1) == -8 );
|
||||
BOOST_TEST( func_c(x,1) == 8 );
|
||||
BOOST_TEST( func_c2(x,1) == 8 );
|
||||
BOOST_TEST( func_c_ref(x,1) == 8 );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
472
include/boost/functional/forward_adapter.hpp
Normal file
472
include/boost/functional/forward_adapter.hpp
Normal file
@@ -0,0 +1,472 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007-2008 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_FORWARD_ADAPTER_HPP_INCLUDED
|
||||
# ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
# include <boost/preprocessor/arithmetic/dec.hpp>
|
||||
|
||||
# include <boost/utility/result_of.hpp>
|
||||
|
||||
# ifndef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 6
|
||||
# elif BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY < 3
|
||||
# undef BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY 3
|
||||
# endif
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
|
||||
class forward_adapter;
|
||||
|
||||
//----- ---- --- -- - - - -
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< class MostDerived, typename Function, typename FunctionConst,
|
||||
int Arity, int MinArity >
|
||||
struct forward_adapter_impl;
|
||||
|
||||
struct forward_adapter_result
|
||||
{
|
||||
template< typename Sig > struct apply;
|
||||
|
||||
// Utility metafunction for qualification adjustment on arguments
|
||||
template< typename T > struct q { typedef T const t; };
|
||||
template< typename T > struct q<T const> { typedef T const t; };
|
||||
template< typename T > struct q<T &> { typedef T t; };
|
||||
|
||||
// Utility metafunction to choose target function qualification
|
||||
template< typename T > struct c
|
||||
{ typedef typename T::target_function_t t; };
|
||||
template< typename T > struct c<T& >
|
||||
{ typedef typename T::target_function_t t; };
|
||||
template< typename T > struct c<T const >
|
||||
{ typedef typename T::target_function_const_t t; };
|
||||
template< typename T > struct c<T const&>
|
||||
{ typedef typename T::target_function_const_t t; };
|
||||
};
|
||||
}
|
||||
|
||||
# define BOOST_TMP_MACRO(f,fn,fc) \
|
||||
boost::detail::forward_adapter_impl< \
|
||||
forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \
|
||||
(MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \
|
||||
:BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY), \
|
||||
(Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) >
|
||||
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class forward_adapter
|
||||
: public BOOST_TMP_MACRO(Function,Function,Function const)
|
||||
, private Function
|
||||
{
|
||||
public:
|
||||
forward_adapter(Function const& f = Function())
|
||||
: Function(f)
|
||||
{ }
|
||||
|
||||
typedef Function target_function_t;
|
||||
typedef Function const target_function_const_t;
|
||||
|
||||
Function & target_function() { return *this; }
|
||||
Function const & target_function() const { return *this; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
|
||||
};
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class forward_adapter< Function const, Arity_Or_MinArity, MaxArity >
|
||||
: public BOOST_TMP_MACRO(Function const, Function const, Function const)
|
||||
, private Function
|
||||
{
|
||||
public:
|
||||
forward_adapter(Function const& f = Function())
|
||||
: Function(f)
|
||||
{ }
|
||||
|
||||
typedef Function const target_function_t;
|
||||
typedef Function const target_function_const_t;
|
||||
|
||||
Function const & target_function() const { return *this; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function const,Function const, Function const)
|
||||
::operator();
|
||||
};
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class forward_adapter< Function &, Arity_Or_MinArity, MaxArity >
|
||||
: public BOOST_TMP_MACRO(Function&, Function, Function)
|
||||
{
|
||||
Function& ref_function;
|
||||
public:
|
||||
forward_adapter(Function& f)
|
||||
: ref_function(f)
|
||||
{ }
|
||||
|
||||
typedef Function target_function_t;
|
||||
typedef Function target_function_const_t;
|
||||
|
||||
Function & target_function() const { return this->ref_function; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
|
||||
};
|
||||
|
||||
#undef BOOST_TMP_MACRO
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< class Self >
|
||||
struct forward_adapter_result::apply< Self() >
|
||||
: boost::result_of< typename c<Self>::t() >
|
||||
{ };
|
||||
|
||||
template< class MD, class F, class FC >
|
||||
struct forward_adapter_impl<MD,F,FC,0,0>
|
||||
{
|
||||
inline typename boost::result_of< FC() >::type
|
||||
operator()() const
|
||||
{
|
||||
return static_cast<MD const*>(this)->target_function()();
|
||||
}
|
||||
|
||||
inline typename boost::result_of< F() >::type
|
||||
operator()()
|
||||
{
|
||||
return static_cast<MD*>(this)->target_function()();
|
||||
}
|
||||
|
||||
// closing brace gets generated by preprocessing code, below
|
||||
|
||||
# define BOOST_TMP_MACRO(tpl_params,arg_types,params,args) \
|
||||
template< tpl_params > \
|
||||
inline typename boost::result_of< FC(arg_types) >::type \
|
||||
operator()(params) const \
|
||||
{ \
|
||||
return static_cast<MD const*>(this)->target_function()(args); \
|
||||
} \
|
||||
template< tpl_params > \
|
||||
inline typename boost::result_of< F(arg_types)>::type \
|
||||
operator()(params) \
|
||||
{ \
|
||||
return static_cast<MD*>(this)->target_function()(args); \
|
||||
}
|
||||
|
||||
# // This is the total number of iterations we need
|
||||
# define count ((1 << BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY+1)-2)
|
||||
|
||||
# // Chain file iteration to virtually one loop
|
||||
# if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 7
|
||||
# define limit1 count
|
||||
# define limit2 0
|
||||
# define limit3 0
|
||||
# else
|
||||
# if BOOST_FUNCTIONAL_FORWARD_ADAPTER_MAX_ARITY <= 15
|
||||
# define limit1 (count >> 8)
|
||||
# define limit2 255
|
||||
# define limit3 0
|
||||
# else
|
||||
# define limit1 (count >> 16)
|
||||
# define limit2 255
|
||||
# define limit3 255
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define N 0
|
||||
|
||||
# define BOOST_PP_FILENAME_1 <boost/functional/forward_adapter.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,limit1)
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef N
|
||||
# undef limit3
|
||||
# undef limit2
|
||||
# undef limit1
|
||||
# undef count
|
||||
# undef BOOST_TMP_MACRO
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::forward_adapter<F,A0,A1> const ()>
|
||||
: boost::detail::forward_adapter_result::template apply<
|
||||
boost::forward_adapter<F,A0,A1> const () >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::forward_adapter<F,A0,A1>()>
|
||||
: boost::detail::forward_adapter_result::template apply<
|
||||
boost::forward_adapter<F,A0,A1>() >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::forward_adapter<F,A0,A1> const& ()>
|
||||
: boost::detail::forward_adapter_result::template apply<
|
||||
boost::forward_adapter<F,A0,A1> const () >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::forward_adapter<F,A0,A1>& ()>
|
||||
: boost::detail::forward_adapter_result::template apply<
|
||||
boost::forward_adapter<F,A0,A1>() >
|
||||
{ };
|
||||
}
|
||||
|
||||
# define BOOST_FUNCTIONAL_FORWARD_ADAPTER_HPP_INCLUDED
|
||||
|
||||
# elif BOOST_PP_ITERATION_DEPTH() == 1 && limit2
|
||||
# define BOOST_PP_FILENAME_2 <boost/functional/forward_adapter.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,limit2)
|
||||
# include BOOST_PP_ITERATE()
|
||||
# elif BOOST_PP_ITERATION_DEPTH() == 2 && limit3
|
||||
# define BOOST_PP_FILENAME_3 <boost/functional/forward_adapter.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS (0,limit3)
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# else
|
||||
|
||||
# // I is the loop counter
|
||||
# if limit2 && limit3
|
||||
# define I (BOOST_PP_ITERATION_1 << 16 | BOOST_PP_ITERATION_2 << 8 | \
|
||||
BOOST_PP_ITERATION_3)
|
||||
# elif limit2
|
||||
# define I (BOOST_PP_ITERATION_1 << 8 | BOOST_PP_ITERATION_2)
|
||||
# else
|
||||
# define I BOOST_PP_ITERATION_1
|
||||
# endif
|
||||
|
||||
# if I < count
|
||||
|
||||
# // Done for this arity? Increment N
|
||||
# if (I+2 >> N+1)
|
||||
# if N == 0
|
||||
# undef N
|
||||
# define N 1
|
||||
# elif N == 1
|
||||
# undef N
|
||||
# define N 2
|
||||
# elif N == 2
|
||||
# undef N
|
||||
# define N 3
|
||||
# elif N == 3
|
||||
# undef N
|
||||
# define N 4
|
||||
# elif N == 4
|
||||
# undef N
|
||||
# define N 5
|
||||
# elif N == 5
|
||||
# undef N
|
||||
# define N 6
|
||||
# elif N == 6
|
||||
# undef N
|
||||
# define N 7
|
||||
# elif N == 7
|
||||
# undef N
|
||||
# define N 8
|
||||
# elif N == 8
|
||||
# undef N
|
||||
# define N 9
|
||||
# elif N == 9
|
||||
# undef N
|
||||
# define N 10
|
||||
# elif N == 10
|
||||
# undef N
|
||||
# define N 11
|
||||
# elif N == 11
|
||||
# undef N
|
||||
# define N 12
|
||||
# elif N == 12
|
||||
# undef N
|
||||
# define N 13
|
||||
# elif N == 13
|
||||
# undef N
|
||||
# define N 14
|
||||
# elif N == 14
|
||||
# undef N
|
||||
# define N 15
|
||||
# elif N == 15
|
||||
# undef N
|
||||
# define N 16
|
||||
# endif
|
||||
|
||||
};
|
||||
|
||||
template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
struct forward_adapter_result::apply< Self(BOOST_PP_ENUM_PARAMS(N,T)) >
|
||||
: boost::result_of<
|
||||
typename c<Self>::t(BOOST_PP_ENUM_BINARY_PARAMS(N,
|
||||
typename q<T,>::t& BOOST_PP_INTERCEPT)) >
|
||||
{ };
|
||||
|
||||
template< class MD, class F, class FC >
|
||||
struct forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
|
||||
{
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename boost::result_of< F(
|
||||
BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT)) >::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT));
|
||||
};
|
||||
|
||||
template< class MD, class F, class FC, int MinArity >
|
||||
struct forward_adapter_impl<MD,F,FC,N,MinArity>
|
||||
: forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>
|
||||
{
|
||||
using forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>::operator();
|
||||
|
||||
# endif
|
||||
|
||||
# // Zero based count for each arity would be I-(1<<N)+2, but we don't
|
||||
# // need it, unless we need a nicer order.
|
||||
|
||||
# // Macros for the parameter's type modifiers.
|
||||
# if I & 0x000001
|
||||
# define PT0 T0 &
|
||||
# else
|
||||
# define PT0 T0 const &
|
||||
# endif
|
||||
# if I & 0x000002
|
||||
# define PT1 T1 &
|
||||
# else
|
||||
# define PT1 T1 const &
|
||||
# endif
|
||||
# if I & 0x000004
|
||||
# define PT2 T2 &
|
||||
# else
|
||||
# define PT2 T2 const &
|
||||
# endif
|
||||
# if I & 0x000008
|
||||
# define PT3 T3 &
|
||||
# else
|
||||
# define PT3 T3 const &
|
||||
# endif
|
||||
# if I & 0x000010
|
||||
# define PT4 T4 &
|
||||
# else
|
||||
# define PT4 T4 const &
|
||||
# endif
|
||||
# if I & 0x000020
|
||||
# define PT5 T5 &
|
||||
# else
|
||||
# define PT5 T5 const &
|
||||
# endif
|
||||
# if I & 0x000040
|
||||
# define PT6 T6 &
|
||||
# else
|
||||
# define PT6 T6 const &
|
||||
# endif
|
||||
# if I & 0x000080
|
||||
# define PT7 T7 &
|
||||
# else
|
||||
# define PT7 T7 const &
|
||||
# endif
|
||||
# if I & 0x000100
|
||||
# define PT8 T8 &
|
||||
# else
|
||||
# define PT8 T8 const &
|
||||
# endif
|
||||
# if I & 0x000200
|
||||
# define PT9 T9 &
|
||||
# else
|
||||
# define PT9 T9 const &
|
||||
# endif
|
||||
# if I & 0x000400
|
||||
# define PT10 T10 &
|
||||
# else
|
||||
# define PT10 T10 const &
|
||||
# endif
|
||||
# if I & 0x000800
|
||||
# define PT11 T11 &
|
||||
# else
|
||||
# define PT11 T11 const &
|
||||
# endif
|
||||
# if I & 0x001000
|
||||
# define PT12 T12 &
|
||||
# else
|
||||
# define PT12 T12 const &
|
||||
# endif
|
||||
# if I & 0x002000
|
||||
# define PT13 T13 &
|
||||
# else
|
||||
# define PT13 T13 const &
|
||||
# endif
|
||||
# if I & 0x004000
|
||||
# define PT14 T14 &
|
||||
# else
|
||||
# define PT14 T14 const &
|
||||
# endif
|
||||
# if I & 0x008000
|
||||
# define PT15 T15 &
|
||||
# else
|
||||
# define PT15 T15 const &
|
||||
# endif
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400))
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename boost::result_of< FC(BOOST_PP_ENUM_PARAMS(N,PT))
|
||||
>::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const
|
||||
{
|
||||
return static_cast<MD const* const>(this)
|
||||
->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
|
||||
}
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename boost::result_of< F(BOOST_PP_ENUM_PARAMS(N,PT))
|
||||
>::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a))
|
||||
{
|
||||
return static_cast<MD* const>(this)
|
||||
->target_function()(BOOST_PP_ENUM_PARAMS(N,a));
|
||||
}
|
||||
# else
|
||||
BOOST_TMP_MACRO(BOOST_PP_ENUM_PARAMS(N,typename T),
|
||||
BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a),
|
||||
BOOST_PP_ENUM_PARAMS(N,a) )
|
||||
// ...generates uglier code but is faster - it caches ENUM_*
|
||||
# endif
|
||||
|
||||
# undef PT0
|
||||
# undef PT1
|
||||
# undef PT2
|
||||
# undef PT3
|
||||
# undef PT4
|
||||
# undef PT5
|
||||
# undef PT6
|
||||
# undef PT7
|
||||
# undef PT8
|
||||
# undef PT9
|
||||
# undef PT10
|
||||
# undef PT11
|
||||
# undef PT12
|
||||
# undef PT13
|
||||
# undef PT14
|
||||
# undef PT15
|
||||
|
||||
# endif // I < count
|
||||
|
||||
# undef I
|
||||
# endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#endif // include guard
|
||||
|
259
include/boost/functional/lightweight_forward_adapter.hpp
Normal file
259
include/boost/functional/lightweight_forward_adapter.hpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/*=============================================================================
|
||||
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_LIGHTWEIGHT_FORWARD_ADAPTER_HPP_INCLUDED
|
||||
# ifndef BOOST_PP_IS_ITERATING
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/iteration/iterate.hpp>
|
||||
# include <boost/preprocessor/repetition/enum.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
# include <boost/preprocessor/facilities/intercept.hpp>
|
||||
|
||||
# include <boost/utility/result_of.hpp>
|
||||
# include <boost/ref.hpp>
|
||||
|
||||
# ifndef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 10
|
||||
# elif BOOST_FUNCTIONAL_FORDWARD_ADAPTER_MAX_ARITY < 3
|
||||
# undef BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY
|
||||
# define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY 3
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template< typename Function, int Arity_Or_MinArity = -1, int MaxArity = -1 >
|
||||
class lightweight_forward_adapter;
|
||||
|
||||
//----- ---- --- -- - - - -
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< class MostDerived, typename Function, typename FunctionConst,
|
||||
int Arity, int MinArity >
|
||||
struct lightweight_forward_adapter_impl;
|
||||
|
||||
struct lightweight_forward_adapter_result
|
||||
{
|
||||
template< typename Sig > struct apply;
|
||||
|
||||
// Utility metafunction for argument transform
|
||||
template< typename T > struct x { typedef T const& t; };
|
||||
template< typename T > struct x< boost::reference_wrapper<T> >
|
||||
{ typedef T& t; };
|
||||
template< typename T > struct x<T&> : x<T> { };
|
||||
template< typename T > struct x<T const&> : x<T> { };
|
||||
template< typename T > struct x<T const> : x<T> { };
|
||||
|
||||
// Utility metafunction to choose target function qualification
|
||||
template< typename T > struct c
|
||||
{ typedef typename T::target_function_t t; };
|
||||
template< typename T > struct c<T& >
|
||||
{ typedef typename T::target_function_t t; };
|
||||
template< typename T > struct c<T const >
|
||||
{ typedef typename T::target_function_const_t t; };
|
||||
template< typename T > struct c<T const&>
|
||||
{ typedef typename T::target_function_const_t t; };
|
||||
};
|
||||
}
|
||||
|
||||
# define BOOST_TMP_MACRO(f,fn,fc) \
|
||||
boost::detail::lightweight_forward_adapter_impl< \
|
||||
lightweight_forward_adapter<f,Arity_Or_MinArity,MaxArity>, fn, fc, \
|
||||
(MaxArity!=-1? MaxArity :Arity_Or_MinArity!=-1? Arity_Or_MinArity \
|
||||
:BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY), \
|
||||
(Arity_Or_MinArity!=-1? Arity_Or_MinArity : 0) >
|
||||
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class lightweight_forward_adapter
|
||||
: public BOOST_TMP_MACRO(Function,Function,Function const)
|
||||
, private Function
|
||||
{
|
||||
public:
|
||||
lightweight_forward_adapter(Function const& f = Function())
|
||||
: Function(f)
|
||||
{ }
|
||||
|
||||
typedef Function target_function_t;
|
||||
typedef Function const target_function_const_t;
|
||||
|
||||
Function & target_function() { return *this; }
|
||||
Function const & target_function() const { return *this; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::lightweight_forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function,Function, Function const)::operator();
|
||||
};
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class lightweight_forward_adapter< Function const, Arity_Or_MinArity,
|
||||
MaxArity >
|
||||
: public BOOST_TMP_MACRO(Function const, Function const, Function const)
|
||||
, private Function
|
||||
{
|
||||
public:
|
||||
lightweight_forward_adapter(Function const& f = Function())
|
||||
: Function(f)
|
||||
{ }
|
||||
|
||||
typedef Function const target_function_t;
|
||||
typedef Function const target_function_const_t;
|
||||
|
||||
Function const & target_function() const { return *this; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::lightweight_forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function const,Function const, Function const)
|
||||
::operator();
|
||||
};
|
||||
template< typename Function, int Arity_Or_MinArity, int MaxArity >
|
||||
class lightweight_forward_adapter< Function &, Arity_Or_MinArity, MaxArity >
|
||||
: public BOOST_TMP_MACRO(Function&, Function, Function)
|
||||
{
|
||||
Function& ref_function;
|
||||
public:
|
||||
lightweight_forward_adapter(Function& f)
|
||||
: ref_function(f)
|
||||
{ }
|
||||
|
||||
typedef Function target_function_t;
|
||||
typedef Function target_function_const_t;
|
||||
|
||||
Function & target_function() const { return this->ref_function; }
|
||||
|
||||
template< typename Sig > struct result
|
||||
: detail::lightweight_forward_adapter_result::template apply<Sig>
|
||||
{ };
|
||||
|
||||
using BOOST_TMP_MACRO(Function&, Function, Function)::operator();
|
||||
};
|
||||
|
||||
#undef BOOST_TMP_MACRO
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template< class Self >
|
||||
struct lightweight_forward_adapter_result::apply< Self() >
|
||||
: boost::result_of< typename c<Self>::t() >
|
||||
{ };
|
||||
|
||||
template< class MD, class F, class FC >
|
||||
struct lightweight_forward_adapter_impl<MD,F,FC,0,0>
|
||||
: lightweight_forward_adapter_result
|
||||
{
|
||||
inline typename boost::result_of< FC() >::type
|
||||
operator()() const
|
||||
{
|
||||
return static_cast<MD const*>(this)->target_function()();
|
||||
}
|
||||
|
||||
inline typename boost::result_of< F() >::type
|
||||
operator()()
|
||||
{
|
||||
return static_cast<MD*>(this)->target_function()();
|
||||
}
|
||||
};
|
||||
|
||||
# define BOOST_PP_FILENAME_1 \
|
||||
<boost/functional/lightweight_forward_adapter.hpp>
|
||||
# define BOOST_PP_ITERATION_LIMITS \
|
||||
(1,BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_MAX_ARITY)
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const ()>
|
||||
: boost::detail::lightweight_forward_adapter_result::template apply<
|
||||
boost::lightweight_forward_adapter<F,A0,A1> const () >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::lightweight_forward_adapter<F,A0,A1>()>
|
||||
: boost::detail::lightweight_forward_adapter_result::template apply<
|
||||
boost::lightweight_forward_adapter<F,A0,A1>() >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::lightweight_forward_adapter<F,A0,A1> const& ()>
|
||||
: boost::detail::lightweight_forward_adapter_result::template apply<
|
||||
boost::lightweight_forward_adapter<F,A0,A1> const () >
|
||||
{ };
|
||||
template<class F, int A0, int A1>
|
||||
struct result_of<boost::lightweight_forward_adapter<F,A0,A1>& ()>
|
||||
: boost::detail::lightweight_forward_adapter_result::template apply<
|
||||
boost::lightweight_forward_adapter<F,A0,A1>() >
|
||||
{ };
|
||||
}
|
||||
|
||||
# define BOOST_FUNCTIONAL_LIGHTWEIGHT_FORWARD_ADAPTER_HPP_INCLUDED
|
||||
|
||||
# else // defined(BOOST_PP_IS_ITERATING)
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template< class Self, BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
struct lightweight_forward_adapter_result::apply<
|
||||
Self (BOOST_PP_ENUM_PARAMS(N,T)) >
|
||||
: boost::result_of<
|
||||
typename c<Self>::t (BOOST_PP_ENUM_BINARY_PARAMS(N,
|
||||
typename x<T,>::t BOOST_PP_INTERCEPT)) >
|
||||
{ };
|
||||
|
||||
template< class MD, class F, class FC >
|
||||
struct lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),N>
|
||||
: lightweight_forward_adapter_result
|
||||
{
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename boost::result_of< F(BOOST_PP_ENUM_BINARY_PARAMS(N,
|
||||
T,const& BOOST_PP_INTERCEPT)) >::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT));
|
||||
};
|
||||
|
||||
template< class MD, class F, class FC, int MinArity >
|
||||
struct lightweight_forward_adapter_impl<MD,F,FC,N,MinArity>
|
||||
: lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),MinArity>
|
||||
{
|
||||
using lightweight_forward_adapter_impl<MD,F,FC,BOOST_PP_DEC(N),
|
||||
MinArity>::operator();
|
||||
|
||||
# define M(z,i,d) \
|
||||
static_cast<typename d::template x<T##i>::t>(a##i)
|
||||
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename lightweight_forward_adapter_result::template apply<
|
||||
MD const (BOOST_PP_ENUM_BINARY_PARAMS(N,
|
||||
T,const& BOOST_PP_INTERCEPT)) >::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a)) const
|
||||
{
|
||||
typedef lightweight_forward_adapter_result _;
|
||||
return static_cast<MD const*>(this)->target_function()(
|
||||
BOOST_PP_ENUM(N,M,_));
|
||||
}
|
||||
template< BOOST_PP_ENUM_PARAMS(N,typename T) >
|
||||
inline typename lightweight_forward_adapter_result::template apply<
|
||||
MD (BOOST_PP_ENUM_BINARY_PARAMS(N,
|
||||
T,const& BOOST_PP_INTERCEPT)) >::type
|
||||
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a))
|
||||
{
|
||||
typedef lightweight_forward_adapter_result _;
|
||||
return static_cast<MD*>(this)->target_function()(
|
||||
BOOST_PP_ENUM(N,M,_));
|
||||
}
|
||||
# undef M
|
||||
};
|
||||
|
||||
# undef N
|
||||
# endif // defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
#endif // include guard
|
||||
|
Reference in New Issue
Block a user