revises function object concepts and functional module documenation to reflect

boost::result_of-based result computation


[SVN r38209]
This commit is contained in:
Tobias Schwinger
2007-07-13 19:25:34 +00:00
parent f05493abf0
commit 9df373af5f
227 changed files with 10684 additions and 4457 deletions

View File

@ -19,7 +19,7 @@ __sequence__, introducing yet another function provides a solution:
invoke(f,my_sequence)
Alternatively it's possible to apply a simple transformation to [^f] in order
Alternatively it is possible to apply a simple transformation to [^f] in order
to achieve the same effect:
f tuple <=> ``f'`` (tuple)
@ -66,44 +66,50 @@ returns an adapter instance for the given argument.
[section Concepts]
[section:callable Callable Object]
[heading Description]
A pointer to a function, a pointer to member function, a pointer to member
data, or a class type whose objects can appear immediately to the left of a
function call operator.
[/ TODO: note about TR1, link to current draft]
[heading Models]
* function pointer types
* member (function or data) pointer types
* all kinds of function objects
[endsect]
[section:poly Polymorphic Function Object]
[section:reg_callable Regular Callable Object]
[heading Description]
[heading Description]
A type of function object with a nested metafunction `result`. `result`
returns the result type of calling the function object, given the argument
types.
A non-member-pointer __callable_obj__ type: A pointer to a function or a class
type whose objects can appear immediately to the left of a function call operator.
[heading Refinement of]
* __callable_obj__
[variablelist Notation
[[`F`][A Polymorphic Function Object type]]
[[`f`][A Polymorphic Function Object]]
[[`T1 ...TN`][Arbitrary types]]
[[`t1 ...tN`][Objects with types `T1 ...TN`]]
[[`F`][A possibly const qualified Deferred Callable Object type]]
[[`f`][An object or reference to an object of type F]]
[[`A1 ...AN`][Argument types]]
[[`a1 ...aN`][Objects or references to objects with types `A1 ...AN`]]
]
[heading Expression requirements]
[table
[[Expression][Return Type][Runtime Complexity]]
[[`f(t1, ...tN)`][`F::result<T1, ...TN>::type`][Unspecified]]
[[`f(a1, ...aN)`][Unspecified][Unspecified]]
]
[heading Models]
* all Fusion __functional_adapters__
* function pointer types
* all kinds of function objects
[endsect]
@ -112,29 +118,71 @@ types.
[heading Description]
__callable_obj__ that works with __boost_result_of__ to determine the result
of a call (such as the function objects provided by the standard library).
__callable_obj__ types that work with __boost_result_of__ to determine the
result of a call.
[heading Refinement of]
* __callable_obj__
[blurb note Once C++ supports the [^decltype] keyword, all models of
__callable_obj__ will also be models of __def_callable_obj__, because
function objects won't need client-side support for `result_of`.
]
[variablelist Notation
[[`F`][A Deferred Callable Object type]]
[[`T1 ...TN`][Arbitrary types]]
[[`F`][A possibly const qualified Deferred Callable Object type]]
[[`A1 ...AN`][Argument types]]
[[`a1 ...aN`][Objects or references to objects with types `A1 ...AN`]]
[[`T1 ...TN`][`T`i is `A`i `&` if `a`i is an __lvalue__, same as `A`i, otherwise]]
]
[heading Expression requirements]
[table
[[Expression][Type]]
[[__boost_result_of_call__`< F(T1 ...TN) >::type`][Unspecified]]
[[__boost_result_of_call__`< F(T1 ...TN) >::type`][Result of a call with `A1 ...AN`-typed arguments]]
]
[heading Models]
* __poly_func_obj__ types
* member (function or data) pointer types
[endsect]
[section:poly Polymorphic Function Object]
[heading Description]
A non-member-pointer __def_callable_obj__ type.
[heading Refinement of]
* __reg_callable_obj__
* __def_callable_obj__
[variablelist Notation
[[`F`][A possibly const-qualified Polymorphic Function Object type]]
[[`f`][An object or reference to an object of type F]]
[[`A1 ...AN`][Argument types]]
[[`a1 ...aN`][Objects or references to objects with types `A1 ...AN`]]
[[`T1 ...TN`][`T`i is `A`i `&` if `a`i is an __lvalue__, same as `A`i, otherwise]]
]
[heading Expression requirements]
[table
[[Expression][Return Type][Runtime Complexity]]
[[`f(a1, ...aN)`][`result_of< F(T1, ...TN) >::type`][Unspecified]]
]
[heading Models]
* function pointers
* function objects of the Standard Library
* all Fusion __functional_adapters__
[endsect]
[endsect]
[/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ]
@ -149,10 +197,6 @@ of a call (such as the function objects provided by the standard library).
Calls a __def_callable_obj__ with the arguments from a __sequence__.
The corresponding metafunction, __result_of_invoke__ does not define a
`type` member for target functions of non-class type whose arity is not
satisfied by the size of the sequence.
The first template parameter can be specialized explicitly to avoid copying
and/or to control the const qualification of a function object.
@ -216,10 +260,6 @@ the result of the call expression.
Calls a __callable_obj__ with the arguments from a __sequence__. The result
of the call is ignored.
The corresponding metafunction, __result_of_invoke_procedure, does not define
a `type` member for target functions of non-class type whose arity is not
satisfied by the size of the sequence.
The first template parameter can be specialized explicitly to avoid copying
and/or to control the const qualification of a function object.
@ -285,10 +325,6 @@ implemented).
Calls a __poly_func_obj__ with the arguments from a __sequence__.
The corresponding metafunction, __result_of_invoke_function_object__, does
not define a `type` member, if the nested `result` class template of the
target function object is empty.
The first template parameter can be specialized explicitly to avoid copying
and/or to control the const qualification of a function object.
@ -316,7 +352,7 @@ and/or to control the const qualification of a function object.
[heading Expression Semantics]
invoke_procedure(f,s);
invoke_function_object(f,s);
[*Return type]: Return type of `f` when invoked with the elements in `s` as its
arguments.
@ -330,11 +366,12 @@ result of the call expression.
[heading Example]
struct sub
{
template<typename T, typename _>
struct result
{
typedef T type;
};
template <typename Sig>
struct result;
template <class Self, typename T>
struct result< Self(T,T) >
{ typedef typename remove_reference<T>::type type; };
template<typename T>
T operator()(T lhs, T rhs) const
@ -366,9 +403,6 @@ result of the call expression.
[heading Description]
Returns the result type of __invoke__.
Empty for non-class target function types whose arity is not satisfied by
the size of the sequence.
[heading Synopsis]
namespace result_of
{
@ -393,9 +427,6 @@ the size of the sequence.
[heading Description]
Returns the result type of __invoke_procedure__.
Empty for non-class target function types whose arity is not satisfied by
the size of the sequence.
[heading Synopsis]
namespace result_of
{
@ -420,8 +451,6 @@ the size of the sequence.
[heading Description]
Returns the result type of __invoke_function_object__.
Empty if the target function's nested `result` class template is empty.
[heading Synopsis]
namespace result_of
{
@ -459,17 +488,13 @@ An unary __poly_func_obj__ adapter template for __def_callable_obj__ target
functions. It takes a __forward_sequence__ that contains the arguments for the
target function.
The nested `result` metafunction does not define a `type` member for target
functions of non-class type whose arity is not satisfied by the size of the
sequence.
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used for an
(in other words, only const versions of [^operator()] can be used for a
target function object that is const or, if the target function object
is held by value, the adapter is const - these semantics have nothing to
do with the const qualification of a member function, which is referring
to the type of object pointed to by [^this] that is specified with the
to the type of object pointed to by [^this] which is specified with the
first element in the sequence passed to the adapter).
If the target function is a pointer to a class members, the corresponding
@ -534,17 +559,15 @@ An unary __poly_func_obj__ adapter template for __callable_obj__ target
functions. It takes a __forward_sequence__ that contains the arguments for
the target function.
The result is discared and the adapter's return type is `void`. The nested
`result` metafunction does not define a `type` member for target functions
of non-class type whose arity is not satisfied by the size of the sequence.
The result is discared and the adapter's return type is `void`.
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used for an
(in other words, only const versions of [^operator()] can be used for a
target function object that is const or, if the target function object
is held by value, the adapter is const - these semantics have nothing to
do with the const qualification of a member function, which is referring
to the type of object pointed to by [^this] that is specified with the
to the type of object pointed to by [^this] which is specified with the
first element in the sequence passed to the adapter).
If the target function is a pointer to a members function, the corresponding
@ -554,8 +577,8 @@ defined (Boost provides this function for [^std::auto_ptr] and
__boost_shared_ptr_call__).
The target function must not be a pointer to a member object (dereferencing
such a pointer without returning anything does not make sense, so it isn't
implemented).
such a pointer without returning anything does not make sense, so this case
is not implemented).
[heading Header]
#include <boost/fusion/functional/adapter/fused_procedure.hpp>
@ -625,8 +648,6 @@ An unary __poly_func_obj__ adapter template for a __poly_func_obj__ target
function. It takes a __forward_sequence__ that contains the arguments for the
target function.
The nested `result` metafunction is inhertied from the target function.
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used for an
@ -680,11 +701,12 @@ is held by value, the adapter is const).
struct sub
{
template<typename T, typename _>
struct result
{
typedef T type;
};
template <typename Sig>
struct result;
template <class Self, typename T>
struct result< Self(T,T) >
{ typedef typename remove_reference<T>::type type; };
template<typename T>
T operator()(T lhs, T rhs) const
@ -726,16 +748,6 @@ compile time expensive operation (see __the_forwarding_problem__ for
details). Therefore, there are two, lightweight and more restricted variants
of this class template, __unfused_lvalue_args__ and __unfused_rvalue_args__.]
The overload set of the adapter's function call operator can be restricted
by removing the `type` member from the nested result metafunction of the
__poly_func_obj__ (in this case the substitution-failure-is-not-an-error
principle applies for non-nullary case and nullary calls are explicitly
disabled by the library).
[caution As the nullary call operator cannot be a template it will be
instantiated along with the class template, so it must be disabled (as
described above) in cases where it isn't instantiable.]
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used if
@ -782,24 +794,27 @@ object is held by value, the adapter is const).
template <typename Function, typename T>
class fused_bound_1st
{
typename traits::__deduce__<Function>::type fnc_deferred;
typename traits::__deduce__<T>::type xxx_bound;
typename traits::deduce<Function>::type fnc_deferred;
typename traits::deduce<T>::type xxx_bound;
public:
fused_bound_1st(Function deferred, T bound)
: fnc_deferred(deferred), xxx_bound(bound)
{ }
template <class Seq>
struct result
: __result_of_invoke__< Function,
typename __result_of_push_front__<Seq, T>::type >
template <typename Sig>
struct result;
template <class Self, class Seq>
struct result< Self(Seq) >
: result_of::invoke< Function, typename result_of::push_front<
typename remove_reference<Seq>::type, T>::type >
{ };
template <class Seq>
typename result<Seq>::type operator()(Seq const & s) const
typename result< void(Seq) >::type operator()(Seq const & s) const
{
return __invoke__(fnc_deferred, push_front(s,xxx_bound));
return invoke(fnc_deferred, push_front(s,xxx_bound));
}
};
@ -819,7 +834,7 @@ object is held by value, the adapter is const).
void try_it()
{
assert(bind_1st(& test_func,3)(-2,-1) == 0);
assert(bind_1st(__std_plus_doc__<float>(), 1)(0.5f) == 1.5f);
assert(bind_1st(std::plus<float>(), 1)(0.5f) == 1.5f);
}
[heading See also]
@ -841,16 +856,6 @@ target function. When called, its arguments are bundled to a
__random_access_sequence__ of references that is passed to the target function
object. Only __lvalue__ arguments are accepted.
The overload set of the adapter's function call operator can be restricted
by removing the `type` member from the nested result metafunction of the
__poly_func_obj__ (in this case the substitution-failure-is-not-an-error
principle applies for non-nullary calls and nullary calls are explicitly
disabled by the library).
[caution As the nullary call operator cannot be a template it will be
instantiated along with the class template, so it must be disabled (as
described above) in cases where it isn't instantiable.]
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used if
@ -933,16 +938,6 @@ target function. When called, its arguments are bundled to a
__random_access_sequence__ of references that is passed to the target
function object. All referenced objects in the sequence are const qualified.
The overload set of the adapter's function call operator can be restricted
by removing the `type` member from the nested result metafunction of the
__poly_func_obj__ (in this case the substitution-failure-is-not-an-error
principle applies for non-nullary calls and nullary calls are explicitly
disabled by the library).
[caution As the nullary call operator cannot be a template it will be
instantiated along with the class template, so it must be disabled (as
described above) in cases where it isn't instantiable.]
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used if
@ -1029,16 +1024,6 @@ The call operators of the resulting function object are strictly typed
By default, call operators with zero to N parameters are generated to,
where N is the size of the __sequence__ that specifies the types.
The overload set of the adapter's function call operator can be restricted
by removing the `type` member from the nested result metafunction of the
__poly_func_obj__ (in this case the substitution-failure-is-not-an-error
principle applies for non-nullary calls and nullary calls are explicitly
disabled by the library).
[caution As the function call operators are not templates, they are
instantiated along with the class template, so they must be disabled (as
described above) in cases where they are not instantiable.]
The type of the target function is allowed to be const qualified or a
reference. Const qualification is preserved and propagated appropriately
(in other words, only const versions of [^operator()] can be used if
@ -1114,38 +1099,40 @@ signature is optimized automatically to avoid by-value parameters.]
: tie_dest(dest)
{ }
template <class Seq>
struct result
{
typedef void type;
};
typedef void result_type;
template <class Seq>
void operator()(Seq const & s) const
{
__for_each__(__zip__(tie_dest,s), __fused__<add_assign>() );
for_each( zip(tie_dest,s), fused<add_assign>() );
}
};
// accepts a tie and creates a typed function object from it
struct fused_parallel_adder_maker
{
template <class Seq>
struct result
template <typename Sig>
struct result;
template <class Self, class Seq>
struct result< Self(Seq) >
{
typedef unfused_typed<fused_parallel_adder<Seq>,
typename mpl::transform<Seq, remove_reference<_> >::type > type;
typedef typename remove_reference<Seq>::type seq;
typedef unfused_typed< fused_parallel_adder<seq>,
typename mpl::transform<seq, remove_reference<_> >::type > type;
};
template <class Seq>
typename result<Seq>::type operator()(Seq const & tie)
typename result< void(Seq) >::type operator()(Seq const & tie)
{
return typename result<Seq>::type(fused_parallel_adder<Seq>(tie));
return typename result< void(Seq) >::type(
fused_parallel_adder<Seq>(tie) );
}
};
__unfused_lvalue_args__<fused_parallel_adder_maker> parallel_add;
unfused_lvalue_args<fused_parallel_adder_maker> parallel_add;
int main()
void try_it()
{
int a = 2; char b = 'X';
// the second call is strictly typed with the types deduced from the
@ -1154,8 +1141,6 @@ signature is optimized automatically to avoid by-value parameters.]
parallel_add(a,b)(3);
parallel_add(a,b)();
assert(a == 8 && b == 'Z');
return 0;
}
[heading See also]
@ -1297,11 +1282,12 @@ The usual __element_conversion__ is applied to the target function.
[heading Example]
struct sub
{
template<typename T, typename _>
struct result
{
typedef T type;
};
template <typename Sig>
struct result;
template <class Self, typename T>
struct result< Self(T,T) >
{ typedef typename remove_reference<T>::type type; };
template<typename T>
T operator()(T lhs, T rhs) const
@ -1357,11 +1343,7 @@ The usual __element_conversion__ is applied to the target function.
[heading Example]
struct bottles_song
{
template<class Seq>
struct result
: mpl::if_< mpl::less< __result_of_size__<Seq>, mpl::int_<2> >,
boost::blank, mpl::identity<void> >::type
{ };
typedef void result_type;
template<class Seq>
void operator()(Seq & s) const