From 0832de9bb36afc25b5e3b152ef6666a10c157cc1 Mon Sep 17 00:00:00 2001 From: Tobias Schwinger Date: Thu, 15 Feb 2007 22:48:01 +0000 Subject: [PATCH] adds functional module [SVN r36956] --- doc/functional.qbk | 1665 ++++++++++++++++++++++++++++++++++++++++++++ doc/fusion.qbk | 52 +- 2 files changed, 1712 insertions(+), 5 deletions(-) create mode 100644 doc/functional.qbk diff --git a/doc/functional.qbk b/doc/functional.qbk new file mode 100644 index 00000000..a56c9725 --- /dev/null +++ b/doc/functional.qbk @@ -0,0 +1,1665 @@ +[section Functional] + +Components to call functions and function objects and to make Fusion code +callable through a function object interface. + +[heading Header] + #include + +[heading Fused and unfused forms] + +What is a function call? + + f (a,b,c) + +It is a name and a tuple written next to each other, left-to-right. + +Although the C++ syntax does not allow to replace [^(a,b,c)] with some Fusion +__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 +to achieve the same effect: + + f tuple <=> ``f'`` (tuple) + +Now, [^f'] is an unary function that takes the arguments to `f` as a tuple; +[^f'] is the /fused/ form of `f`. +Reading the above equivalence right-to-left to get the inverse transformation, +`f` is the /unfused/ form of [^f']. + +[heading Calling functions and function objects] + +Having generic C++ code call back arbitrary functions provided by the client +used to be a heavily repetitive task, as different functions can differ in +arity, invocation syntax and other properties that might be part of the type. +Transporting arguments as Fusion sequences and factoring out the invocation +makes Fusion algorithms applicable to function arguments and also reduces +the problem to one invocation syntax and a fixed arity (instead of an arbitrary +number of arbitrary arguments times several syntactic variants times additional +properties). + +Transforming an unfused function into its fused counterpart allows n-ary +calls from an algorithm that invokes an unary __poly_func_obj__ with +__sequence__ arguments. + +The library provides several function templates to invoke different kinds of +functions and adapters to transform them into fused form, respectively. +Every variant has a corresponding generator function template that returns +an adapter instance for the given argument. + +[heading Making Fusion code callable through a function object interface] + +Transforming a fused function into its unfused counterpart allows to create +function objects to accept arbitrary calls. In other words, an unary function +object can be implemented instead of (maybe heavily overloaded) function +templates or function call operators. + +The library provides several adapter variants that implement this +transformation, ranging from strictly typed to fully generic. The latter +provides a reusable solution to __the_forwarding_problem__. +Every generic variant has a corresponding generator function template that +returns an adapter instance for the given argument. + +[/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ] + +[section Concepts] + +[section:callable Callable Object] + +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] + +[endsect] + + +[section:poly Polymorphic Function Object] + +[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. + +[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`]] +] + +[heading Expression requirements] + +[table + [[Expression][Return Type][Runtime Complexity]] + [[`f(t1, ...tN)`][`F::result::type`][Unspecified]] +] + +[heading Models] +* all Fusion __functional_adapters__ + +[endsect] + + +[section:def_callable Deferred Callable Object] + +[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). + +[heading Refinement of] +* __callable_obj__ + +[variablelist Notation + [[`F`][A Deferred Callable Object type]] + [[`T1 ...TN`][Arbitrary types]] +] + +[heading Expression requirements] + +[table + [[Expression][Type]] + [[__boost_result_of_call__`< F(T1 ...TN) >::type`][Unspecified]] +] + +[heading Models] +* all Fusion __functional_adapters__ + +[endsect] + +[endsect] + +[/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ] + +[section Invocation] + +[section Functions] + +[section invoke] + +[heading Description] + +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. + +If the target function is a pointer to a class members, the corresponding +object can be specified as a reference, pointer, or smart pointer. +In case of the latter, a freestanding [^get_pointer] function must be +defined (Boost provides this function for [^std::auto_ptr] and +__boost_shared_ptr_call__). + +[heading Synopsis] + template< + typename Function, + class Sequence + > + typename __result_of_invoke__::type + invoke(Function f, Sequence & s); + + template< + typename Function, + class Sequence + > + typename __result_of_invoke__::type + invoke(Function f, Sequence const & s); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [A __def_callable_obj__] [The function to call.]] + [[`s`] [A __forward_sequence__] [The arguments.]] +] + +[heading Expression Semantics] + + invoke(f,s); + +[*Return type]: Return type of `f` when invoked with the elements in `s` as its +arguments. + +[*Semantics]: Invokes `f` with the elements in `s` as arguments and returns +the result of the call expression. + +[heading Header] + #include + +[heading Example] + __std_plus_doc__ add; + assert(invoke(add,__make_vector__(1,1)) == 2); + +[heading See also] +* __invoke_procedure__ +* __invoke_function_object__ +* __result_of_invoke__ +* __fused__ + +[endsect] + +[section invoke_procedure] + +[heading Description] + +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. + +For pointers to class members corresponding object can be specified as +a reference, pointer, or smart pointer. In case of the latter, a freestanding +[^get_pointer] function must be 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). + +[heading Synopsis] + template< + typename Function, + class Sequence + > + typename __result_of_invoke_procedure__::type + invoke_procedure(Function f, Sequence & s); + + template< + typename Function, + class Sequence + > + typename __result_of_invoke_procedure__::type + invoke_procedure(Function f, Sequence const & s); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __callable_obj__] [The function to call.]] + [[`s`] [Model of __forward_sequence__] [The arguments.]] +] + +[heading Expression Semantics] + + invoke_procedure(f,s); + +[*Return type]: `void` + +[*Semantics]: Invokes `f` with the elements in `s` as arguments. + +[heading Header] + #include + +[heading Example] + __vector__ v(1,2); + using namespace boost::lambda; + invoke_procedure(_1 += _2, v); + assert(__front__(v) == 3); + +[heading See also] +* __invoke__ +* __invoke_function_object__ +* __result_of_invoke_procedure__ +* __fused_procedure__ + +[endsect] + +[section invoke_function_object] + +[heading Description] + +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. + +[heading Synopsis] + template< + typename Function, + class Sequence + > + typename __result_of_invoke_function_object__::type + invoke_function_object(Function f, Sequence & s); + + template< + typename Function, + class Sequence + > + typename __result_of_invoke_function_object__::type + invoke_function_object(Function f, Sequence const & s); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __poly_func_obj__] [The function object to call.]] + [[`s`] [Model of __forward_sequence__] [The arguments.]] +] + +[heading Expression Semantics] + + invoke_procedure(f,s); + +[*Return type]: Return type of `f` when invoked with the elements in `s` as its +arguments. + +[*Semantics]: Invokes `f` with the elements in `s` as arguments and returns the +result of the call expression. + +[heading Header] + #include + +[heading Example] + struct sub + { + template + struct result + { + typedef T type; + }; + + template + T operator()(T lhs, T rhs) const + { + return lhs - rhs; + } + }; + + void try_it() + { + sub f; + assert(f(2,1) == invoke_function_object(f,__make_vector__(2,1))); + } + +[heading See also] +* __invoke__ +* __invoke_procedure__ +* __result_of_invoke_function_object__ +* __fused_function_object__ + +[endsect] + +[endsect] [/ Functions] + +[section Metafunctions] + +[section invoke] + +[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 + { + template< + typename Function, + class Sequence + > + struct invoke + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __invoke__ +* __fused__ + +[endsect] + +[section invoke_procedure] + +[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 + { + template< + typename Function, + class Sequence + > + struct invoke_procedure + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __invoke_procedure__ +* __fused_procedure__ + +[endsect] + +[section invoke_function_object] + +[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 + { + template< + class Function, + class Sequence + > + struct invoke_function_object + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __invoke_function_object__ +* __fused_function_object__ + +[endsect] + +[endsect] [/ Metafunctions ] + +[endsect] [/ Invocation ] + +[/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ] + +[section:adapters Adapters] + +Function object templates to transform a particular target function. + +[section fused] + +[heading Description] + +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 +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], 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 +object can be specified as a reference, pointer, or smart pointer. +In case of the latter, a freestanding [^get_pointer] function must be +defined (Boost provides this function for [^std::auto_ptr] and +__boost_shared_ptr_call__). + +[heading Header] + #include + +[heading Synopsis] + template + class fused; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [A __def_callable_obj__] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`R`] [A possibly const qualified __def_callable_obj__ type or reference type thereof]] + [[`r`] [An object convertible to `R`]] + [[`s`] [A __sequence__ of arguments that are accepted by `r`]] + [[`f`] [An instance of `fused`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`fused(r)`] [Creates a fused function as described above, initializes the target function with `r`.]] + [[`fused()`] [Creates a fused function as described above, attempts to use `R`'s default constructor.]] + [[`f(s)`] [Calls `r` with the elements in `s` as its arguments.]] +] + +[heading Example] + fused< __std_plus_doc__ > f; + assert(f(__make_vector__(1,2l)) == 3l); + +[heading See also] + +* __fused_procedure__ +* __fused_function_object__ +* __invoke__ +* __deduce__ + +[endsect] + +[section fused_procedure] + +[heading Description] + +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 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 +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], 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 +object can be specified as a reference, pointer, or smart pointer. +In case of the latter, a freestanding [^get_pointer] function must be +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). + +[heading Header] + #include + +[heading Synopsis] + template + class fused_procedure; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [__callable_obj__ type] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`R`] [A possibly const qualified __callable_obj__ type or reference type thereof]] + [[`r`] [An object convertible to `R`]] + [[`s`] [A __sequence__ of arguments that are accepted by `r`]] + [[`f`] [An instance of `fused`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`fused_procedure(r)`] [Creates a fused function as described above, initializes the target function with `r`.]] + [[`fused_procedure()`] [Creates a fused function as described above, attempts to use `R`'s default constructor.]] + [[`f(s)`] [Calls `r` with the elements in `s` as its arguments.]] +] + +[heading Example] + template + void n_ary_for_each(SequenceOfSequences const & s, Func const & f) + { + __for_each__(__zip_view__(s), + fused_procedure(f)); + } + + void try_it() + { + __vector__ a(2,2.0f); + __vector__ b(1,1.5f); + using namespace boost::lambda; + n_ary_for_each(__vector_tie__(a,b), _1 -= _2); + assert(a == __make_vector__(1,0.5f)); + } + +[heading See also] + +* __fused__ +* __fused_function_object__ +* __invoke_procedure__ + +[endsect] + +[section fused_function_object] + +[heading Description] + +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 +target function object that is const or, if the target function object +is held by value, the adapter is const). + +[heading Header] + #include + +[heading Synopsis] + template + class fused_function_object; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [__poly_func_obj__ type] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`R`] [A possibly const qualified __poly_func_obj__ type or reference type thereof]] + [[`r`] [An object convertible to `R`]] + [[`s`] [A __sequence__ of arguments that are accepted by `r`]] + [[`f`] [An instance of `fused`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`fused_function_object(r)`] [Creates a fused function as described above, initializes the target function with `r`.]] + [[`fused_function_object()`] [Creates a fused function as described above, attempts to use `R`'s default constructor.]] + [[`f(s)`] [Calls `r` with the elements in `s` as its arguments.]] +] + +[heading Example] + template + typename __result_of_transform__< zip_view const, + fused_function_object >::type + n_ary_transform(SeqOfSeqs const & s, Func const & f) + { + return __transform__(zip_view(s), + fused_function_object(f)); + } + + struct sub + { + template + struct result + { + typedef T type; + }; + + template + T operator()(T lhs, T rhs) const + { + return lhs - rhs; + } + }; + + void try_it() + { + __vector__ a(2,2.0f); + __vector__ b(1,1.5f); + __vector__ c(1,0.5f); + assert(c == n_ary_transform(__vector_tie__(a,b), sub())); + } + +[heading See also] + +* __fused__ +* __fused_procedure__ +* __invoke_function_object__ +* __deduce__ + +[endsect] + + +[section unfused_generic] + +[heading Description] + +An n-ary __poly_func_obj__ adapter template for an unary __poly_func_obj__ +target function. When called, its arguments are bundled to a +__random_access_sequence__ of references that is passed to the target function. +Non-const __lvalue__ arguments are transported as references to non-const, otherwise +references to const are used. + +[tip Detecting mutable LValues on a per-argument basis is currently a +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 +the target function object is const - or, in case the target function +object is held by value, the adapter is const). + +[heading Header] + #include + +[heading Synopsis] + template + class unfused_generic; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [An unary __poly_func_obj__] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`F`] [A possibly const qualified, unary __poly_func_obj__ type or reference type thereof]] + [[`f`] [An object convertible to `F`]] + [[`UG`] [The type `unfused_generic`]] + [[`ug`] [An instance of `UG`, initialized with `f`]] + [[`a0`...`aN`] [Arguments to `ug`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`UG(f)`] [Creates a fused function as described above, initializes the target function with `f`.]] + [[`UG()`] [Creates a fused function as described above, attempts to use `F`'s default constructor.]] + [[`ug(a0`...`aN)`] [Calls `f` with a __sequence__ that contains references to the arguments `a0`...`aN`.]] +] + +[heading Example] + template + class fused_bound_1st + { + typename traits::__deduce__::type fnc_deferred; + typename traits::__deduce__::type xxx_bound; + public: + + fused_bound_1st(Function deferred, T bound) + : fnc_deferred(deferred), xxx_bound(bound) + { } + + template + struct result + : __result_of_invoke__< Function, + typename __result_of_push_front__::type > + { }; + + template + typename result::type operator()(Seq const & s) const + { + return __invoke__(fnc_deferred, push_front(s,xxx_bound)); + } + }; + + template + unfused_generic< fused_bound_1st > + bind_1st(Function f, T const & x) + { + return unfused_generic< fused_bound_1st >( + fused_bound_1st(f,x) ); + } + + int test_func(int a, int b, int c) + { + return a+b+c; + } + + void try_it() + { + assert(bind_1st(& test_func,3)(-2,-1) == 0); + assert(bind_1st(__std_plus_doc__(), 1)(0.5f) == 1.5f); + } + +[heading See also] +* __unfused_lvalue_args__ +* __unfused_rvalue_args__ +* __unfused_typed__ +* __deduce__ +* __deduce_sequence__ + +[endsect] + + +[section unfused_lvalue_args] + +[heading Description] + +An n-ary __poly_func_obj__ adapter template for an unary __poly_func_obj__ +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 +the target function object is const - or, in case the target function +object is held by value, the adapter is const). + +[heading Header] + #include + +[heading Synopsis] + template + class unfused_lvalue_args; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [A unary __poly_func_obj__] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`F`] [A possibly const qualified, unary __poly_func_obj__ type or reference type thereof]] + [[`f`] [An object convertible to `F`]] + [[`UL`] [The type `unfused_lvalue_args`]] + [[`ul`] [An instance of `UL`, initialized with `f`]] + [[`a0`...`aN`] [Arguments to `ul`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`UL(f)`] [Creates a fused function as described above, initializes the target function with `f`.]] + [[`UL()`] [Creates a fused function as described above, attempts to use `F`'s default constructor.]] + [[`ul(a0`...`aN)`] [Calls `f` with a __sequence__ that contains references to the arguments `a0`...`aN`.]] +] + +[heading Example] + struct fused_incrementer + { + template + struct result + { + typedef void type; + }; + + template + void operator()(Seq const & s) const + { + __for_each__(s,++boost::lambda::_1); + } + }; + + void try_it() + { + unfused_lvalue_args increment; + int a = 2; char b = 'X'; + increment(a,b); + assert(a == 3 && b == 'Y'); + } + +[heading See also] +* __unfused_rvalue_args__ +* __unfused_generic__ +* __unfused_typed__ + +[endsect] + +[section unfused_rvalue_args] + +[heading Description] + +An n-ary __poly_func_obj__ adapter template for an unary __poly_func_obj__ +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 +the target function object is const - or, in case the target function object +is held by value, the adapter is const). + +[heading Header] + #include + +[heading Synopsis] + template + class unfused_rvalue_args; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [A unary __poly_func_obj__] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`F`] [A possibly const qualified, unary __poly_func_obj__ type or reference type thereof]] + [[`f`] [An object convertible to `F`]] + [[`UR`] [The type `unfused_rvalue_args`]] + [[`ur`] [An instance of `UR`, initialized with `f`]] + [[`a0`...`aN`] [Arguments to `ur`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`UR(f)`] [Creates a fused function as described above, initializes the target function with `f`.]] + [[`UR()`] [Creates a fused function as described above, attempts to use `F`'s default constructor.]] + [[`ur(a0`...`aN)`] [Calls `f` with a __sequence__ that contains references to the arguments `a0`...`aN`.]] +] + +[heading Example] + struct sequence_printer + { + template + struct result + { + typedef void type; + }; + + template + void operator()(Seq const & s) const + { + std::cout << s << std::endl; + } + }; + + void try_it() + { + unfused_rvalue_args print; + print(24,"bottles of beer in",'a',"box."); + } + +[heading See also] +* __unfused_lvalue_args__ +* __unfused_generic__ +* __unfused_typed__ +* __deduce__ +* __deduce_sequence__ + +[endsect] + +[section unfused_typed] + +[heading Description] + +An n-ary __poly_func_obj__ adapter template for an unary __poly_func_obj__ +target function. When called, its arguments are bundled to a +__random_access_sequence__ that is passed to the target function object. + +The call operators of the resulting function object are strictly typed +(in other words, non-templatized) with the types from a __sequence__. +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 +the target function object is const - or, in case the target function object +is held by value, the adapter is const). + +[tip If the type sequence passed to this template contains non-reference +elements, the element is copied only once - the call operator's signature +is optimized automatically to avoid by-value parameters.] + +[heading Header] + #include + +[heading Synopsis] + template + class unfused_typed; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Function`] [A unary __poly_func_obj__] []] + [[`Sequence`] [A __sequence__] []] +] + +[heading Model of] + +* __poly_func_obj__ +* __def_callable_obj__ + +[variablelist Notation + [[`F`] [A possibly const qualified, unary __poly_func_obj__ type or reference type thereof]] + [[`f`] [An object convertible to `F`]] + [[`S`] [A __sequence__ of parameter types]] + [[`UT`] [The type `unfused_typed`]] + [[`ut`] [An instance of `UT`, initialized with `f`]] + [[`a0`...`aN`] [Arguments to `ut`, convertible to the types in `S`]] +] + +[heading Expression Semantics] + +[table + [[Expression] [Semantics]] + [[`UT(f)`] [Creates a fused function as described above, initializes the target function with `f`.]] + [[`UT()`] [Creates a fused function as described above, attempts to use `F`'s default constructor.]] + [[`ut(a0`...`aN)`] [Calls `f` with an instance of `S` (or a subsequence of `S` starting at the first element, + if fewer arguments are given and the overload hasn't been disabled) initialized with + `a0`...`aN`.]] +] + +[heading Example] + struct add_assign // applies operator+= + { + typedef void result_type; // for simplicity + + template + void operator()(T & lhs, T const & rhs) const + { + lhs += rhs; + } + }; + + template + class fused_parallel_adder + { + Tie tie_dest; + public: + explicit fused_parallel_adder(Tie const & dest) + : tie_dest(dest) + { } + + template + struct result + { + typedef void type; + }; + + template + void operator()(Seq const & s) const + { + __for_each__(__zip__(tie_dest,s), __fused__() ); + } + }; + + // accepts a tie and creates a typed function object from it + struct fused_parallel_adder_maker + { + template + struct result + { + typedef unfused_typed, + typename mpl::transform >::type > type; + }; + + template + typename result::type operator()(Seq const & tie) + { + return typename result::type(fused_parallel_adder(tie)); + } + }; + __unfused_lvalue_args__ parallel_add; + + int main() + { + int a = 2; char b = 'X'; + // the second call is strictly typed with the types deduced from the + // first call + parallel_add(a,b)(3,2); + parallel_add(a,b)(3); + parallel_add(a,b)(); + assert(a == 8 && b == 'Z'); + + return 0; + } + +[heading See also] +* __unfused_generic__ +* __unfused_lvalue_args__ +* __unfused_rvalue_args__ +* __deduce__ +* __deduce_sequence__ + +[endsect] + +[endsect] [/ Adapters] + +[/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ] + +[section Generation] + +[section Functions] + +[section make_fused] + +[heading Description] +Creates a __fused__ adapter for a given __def_callable_obj__. The usual +__element_conversion__ is applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_fused__::type + make_fused(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __def_callable_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_fused(f); + +[*Return type]: A specialization of __fused__. + +[*Semantics]: Returns a __fused__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + float sub(float a, float b) { return a - b; } + + void try_it() + { + __vector__ a(2,2.0f); + __vector__ b(1,1.5f); + __vector__ c(1.0f,0.5f); + assert(c == __transform__(__zip__(a,b), make_fused(& sub))); + assert(c == __transform__(__zip__(a,b), make_fused(__std_minus_doc__()))); + } + +[heading See also] +* __fused__ +* __deduce__ +* __result_of_make_fused__ + +[endsect] + +[section make_fused_procedure] + +[heading Description] +Creates a __fused_procedure__ adapter for a given __def_callable_obj__. +The usual __element_conversion__ applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_fused_procedure__::type + make_fused_procedure(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __callable_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_fused_procedure(f); + +[*Return type]: A specialization of __fused_procedure__. + +[*Semantics]: Returns a __fused_procedure__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + __vector__ v(1,2,3); + using namespace boost::lambda; + make_fused_procedure(_1 += _2 - _3)(v); + assert(__front__(v) == 0); + +[heading See also] +* __fused_procedure__ +* __deduce__ +* __result_of_make_fused_procedure__ + +[endsect] + +[section make_fused_function_object] + +[heading Description] +Creates a __fused_function_object__ adapter for a given __def_callable_obj__. +The usual __element_conversion__ is applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_fused_function_object__::type + make_fused_function_object(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __poly_func_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_fused_function_object(f); + +[*Return type]: A specialization of __fused_function_object__. + +[*Semantics]: Returns a __fused_function_object__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + struct sub + { + template + struct result + { + typedef T type; + }; + + template + T operator()(T lhs, T rhs) const + { + return lhs - rhs; + } + }; + + void try_it() + { + __vector__ a(2,2.0f); + __vector__ b(1,1.5f); + __vector__ c(1,0.5f); + assert(c == __transform__(__zip__(a,b), make_fused_function_object(sub()))); + } + +[heading See also] +* __fused_function_object__ +* __deduce__ +* __result_of_make_fused_function_object__ + +[endsect] + +[section make_unfused_generic] + +[heading Description] +Creates a __unfused_generic__ adapter for a given, unary __poly_func_obj__. +The usual __element_conversion__ is applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_unfused_generic__::type + make_unfused_generic(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __poly_func_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_unfused_generic(f); + +[*Return type]: A specialization of __unfused_generic__. + +[*Semantics]: Returns a __unfused_generic__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + struct bottles_song + { + template + struct result + : mpl::if_< mpl::less< __result_of_size__, mpl::int_<2> >, + boost::blank, mpl::identity >::type + { }; + + template + void operator()(Seq & s) const + { + typename result_of::at_c::type n = at_c<0>(s); + typename result_of::at_c::type what = at_c<1>(s); + + std::cout + << n << " bottles of " << what << " on the wall.\n" + << n << " bottles of " << what << "!\n" + << "Take one down - pass it around.\n"; + + n -= 1; // glug glug... + + std::cout + << n << " bottles of " << what << " on the wall.\n" + << std::endl; + } + }; + + void try_it() + { + unsigned n_milk = 99; + for(int i = 0; i < 3; ++i) + make_unfused_generic(bottles_song())(n_milk,"milk"); + // 96 bottles left for me + } + +[heading See also] +* __unfused_generic__ +* __deduce__ +* __result_of_make_unfused_generic__ + +[endsect] + +[section make_unfused_lvalue_args] + +[heading Description] +Creates a __unfused_lvalue_args__ adapter for a given, unary __poly_func_obj__. +The usual __element_conversion__ is applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_unfused_lvalue_args__::type + make_unfused_lvalue_args(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __poly_func_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_unfused_lvalue_args(f); + +[*Return type]: A specialization of __unfused_lvalue_args__. + +[*Semantics]: Returns a __unfused_lvalue_args__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + struct fused_incrementer + { + template + struct result + { + typedef void type; + }; + + template + void operator()(Seq const & s) const + { + __for_each__(s,++boost::lambda::_1); + } + }; + + void try_it() + { + int a = 2; char b = 'X'; + make_unfused_lvalue_args(fused_incrementer())(a,b); + assert(a == 3 && b == 'Y'); + } + +[heading See also] +* __unfused_lvalue_args__ +* __deduce__ +* __result_of_make_unfused_lvalue_args__ + +[endsect] + +[section make_unfused_rvalue_args] + +[heading Description] +Creates a __unfused_rvalue_args__ adapter for a given, unary __poly_func_obj__. +The usual __element_conversion__ is applied to the target function. + +[heading Synopsis] + template + inline typename __result_of_make_unfused_rvalue_args__::type + make_unfused_rvalue_args(F const & f); + +[heading Parameters] +[table + [[Parameter] [Requirement] [Description]] + [[`f`] [Model of __poly_func_obj__] [The function to transform.]] +] + +[heading Expression Semantics] + + make_unfused_rvalue_args(f); + +[*Return type]: A specialization of __unfused_rvalue_args__. + +[*Semantics]: Returns a __unfused_rvalue_args__ adapter for `f`. + +[heading Header] + + #include + +[heading Example] + struct sequence_printer + { + template + struct result + { + typedef void type; + }; + + template + void operator()(Seq const & s) const + { + std::cout << s << std::endl; + } + }; + + void try_it() + { + make_unfused_rvalue_args(sequence_printer()) + (24,"bottles of beer in",'a',"box."); + } + +[heading See also] +* __unfused_rvalue_args__ +* __deduce__ +* __result_of_make_unfused_rvalue_args__ + +[endsect] + +[endsect] [/ Functions] + +[section Metafunctions] + +[section make_fused] + +[heading Description] +Returns the result type of __make_fused__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_fused + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_fused__ + +[endsect] + +[section make_fused_procedure] + +[heading Description] +Returns the result type of __make_fused_procedure__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_fused_procedure + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_fused_procedure__ + +[endsect] + +[section make_fused_function_object] + +[heading Description] +Returns the result type of __make_fused_function_object__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_fused_function_object + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_fused_function_object__ + +[endsect] + +[section make_unfused_generic] + +[heading Description] +Returns the result type of __make_unfused_generic__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_unfused_generic + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_unfused_generic__ + +[endsect] + +[section make_unfused_lvalue_args] + +[heading Description] +Returns the result type of __make_unfused_lvalue_args__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_unfused_lvalue_args + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_unfused_lvalue_args__ + +[endsect] + +[section make_unfused_rvalue_args] + +[heading Description] +Returns the result type of __make_unfused_rvalue_args__. + +[heading Header] + + #include + +[heading Synopsis] + namespace result_of + { + template + struct make_unfused_rvalue_args + { + typedef __unspecified__ type; + }; + } + +[heading See also] +* __make_unfused_rvalue_args__ + +[endsect] + +[endsect] [/ Metafunctions] + +[endsect] [/ Generation] + +[endsect] [/ Functional ] diff --git a/doc/fusion.qbk b/doc/fusion.qbk index 032bafa1..0f1d006f 100644 --- a/doc/fusion.qbk +++ b/doc/fusion.qbk @@ -29,6 +29,8 @@ [def __mlist_archive__ [@http://news.gmane.org/gmane.comp.parsers.spirit.general]] [def __jaakko_jarvi__ [@http://www.boost.org/people/jaakko_jarvi.htm Jaakko Jarvi]] [def __david_abrahams__ [@http://www.boost.org/people/dave_abrahams.htm David Abrahams]] +[def __the_forwarding_problem__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm The Forwarding Problem]] + [def __boost_any__ [@http://boost.org/doc/html/any.html Boost.Any]] [def __new_iterator_concepts__ [@http://boost.org/libs/iterator/doc/new-iter-concepts.html New Iterator Concepts]] [def __boost_array_library__ [@http://www.boost.org/doc/html/array.html Boost.Array Library]] @@ -36,12 +38,19 @@ [def __boost_tuple_library__ [@http://www.boost.org/libs/tuple/doc/tuple_users_guide.html Boost.Tuple Library]] [def __boost_ref__ [@http://www.boost.org/doc/html/ref.html Boost.Ref]] [def __boost_ref_call__ [@http://www.boost.org/doc/html/ref.html `ref`]] +[def __boost_result_of__ [@http://www.boost.org/libs/utility/utility.htm#result_of Boost.ResultOf]] +[def __boost_result_of_call__ [@http://www.boost.org/libs/utility/utility.htm#result_of `boost::result_of`]] +[def __boost_enable_if__ [@http://www.boost.org/libs/utility/enable_if.html Boost.EnableIf utility]] +[def __boost_shared_ptr_call__ [@http://www.boost.org/libs/smart_ptr/smart_ptr.hpp `boost::shared_ptr`]] [def __std_pair_doc__ [@http://www.sgi.com/tech/stl/pair.html `std::pair`]] +[def __std_plus_doc__ [@http://www.sgi.com/tech/stl/plus.html `std::plus`]] +[def __std_minus_doc__ [@http://www.sgi.com/tech/stl/minus.html `std::minus`]] + +[def __mpl_integral_constant__ [@http://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html MPL Integral Constant]] +[def __mpl_boolean_constant__ [@http://www.boost.org/libs/mpl/doc/refmanual/integral-constant.html MPL Boolean Constant]] +[def __mpl_metafunction_class__ [@http://www.boost.org/libs/mpl/doc/refmanual/metafunction-class.html MPL Metafunction Class]] +[def __mpl_lambda_expression__ [@http://www.boost.org/libs/mpl/doc/refmanual/lambda-expression.html MPL Lambda Expression]] -[def __mpl_integral_constant__ MPL Integral Constant] -[def __mpl_boolean_constant__ MPL Boolean Constant] -[def __mpl_metafunction_class__ MPL Metafunction Class] -[def __mpl_lambda_expression__ MPL Lambda Expression] [def __lvalue__ LValue] [def __unspecified__ /unspecified/] @@ -103,6 +112,7 @@ [def __joint_view__ [link fusion.sequences.views.joint_view `joint_view`]] [def __transform_view__ [link fusion.sequences.views.transform_view `transform_view`]] [def __reverse_view__ [link fusion.sequences.views.reverse_view `reverse_view`]] +[def __zip_view__ [link fusion.sequences.views.zip_view `zip_view`]] [def __std_pair__ [link fusion.sequences.adapted.std__pair `std::pair`]] [def __boost_array__ [link fusion.sequences.adapted.boost__array `boost::array`]] @@ -176,7 +186,6 @@ [def __algorithm__ [link fusion.algorithms Algorithm]] [def __algorithms__ [link fusion.algorithms Algorithms]] -[def __poly_func_obj__ [link fusion.algorithms.concepts.poly Polymorphic Function Object]] [def __fold__ [link fusion.algorithms.iteration.functions.fold `fold`]] [def __result_of_fold__ [link fusion.algorithms.iteration.metafunctions.fold `result_of::fold`]] [def __accumulate__ [link fusion.algorithms.iteration.functions.accumulate `accumulate`]] @@ -239,6 +248,38 @@ [def __tr1_tuple_pair__ [link fusion.tuples.pairs `TR1 and std::pair`]] [def __tuple_get__ [link fusion.tuples.class_template_tuple.element_access `get`]] +[def __callable_obj__ [link fusion.functional.concepts.callable Callable Object]] +[def __poly_func_obj__ [link fusion.functional.concepts.poly Polymorphic Function Object]] +[def __def_callable_obj__ [link fusion.functional.concepts.def_callable Deferred Callable Object]] +[def __functional_adapters__ [link fusion.functional.adapters functional adapters]] +[def __fused__ [link fusion.functional.adapters.fused `fused`]] +[def __fused_procedure__ [link fusion.functional.adapters.fused_procedure `fused_procedure`]] +[def __fused_function_object__ [link fusion.functional.adapters.fused_function_object `fused_function_object`]] +[def __unfused_generic__ [link fusion.functional.adapters.unfused_generic `unfused_generic`]] +[def __unfused_lvalue_args__ [link fusion.functional.adapters.unfused_lvalue_args `unfused_lvalue_args`]] +[def __unfused_rvalue_args__ [link fusion.functional.adapters.unfused_rvalue_args `unfused_rvalue_args`]] +[def __unfused_typed__ [link fusion.functional.adapters.unfused_typed `unfused_typed`]] +[def __invoke__ [link fusion.functional.invocation.functions.invoke `invoke`]] +[def __invoke_procedure__ [link fusion.functional.invocation.functions.invoke_procedure `invoke_procedure`]] +[def __invoke_function_object__ [link fusion.functional.invocation.functions.invoke_function_object `invoke_function_object`]] +[def __make_fused__ [link fusion.functional.generation.functions.make_fused `make_fused`]] +[def __make_fused_procedure__ [link fusion.functional.generation.functions.make_fused_procedure `make_fused_procedure`]] +[def __make_fused_function_object__ [link fusion.functional.generation.functions.make_fused_function_object `make_fused_function_object`]] +[def __make_unfused_generic__ [link fusion.functional.generation.functions.make_unfused_generic `make_unfused_generic`]] +[def __make_unfused_rvalue_args__ [link fusion.functional.generation.functions.make_unfused_rvalue_args `make_unfused_rvalue_args`]] +[def __make_unfused_lvalue_args__ [link fusion.functional.generation.functions.make_unfused_lvalue_args `make_unfused_lvalue_args`]] +[def __make_unfused_typed__ [link fusion.functional.generation.functions.make_unfused_typed `make_unfused_typed`]] +[def __result_of_invoke__ [link fusion.functional.invocation.metafunctions.invoke `result_of::invoke`]] +[def __result_of_invoke_procedure__ [link fusion.functional.invocation.metafunctions.invoke_procedure `result_of::invoke_procedure`]] +[def __result_of_invoke_function_object__ [link fusion.functional.invocation.metafunctions.invoke_function_object `result_of::invoke_function_object`]] +[def __result_of_make_fused__ [link fusion.functional.generation.metafunctions.make_fused `make_fused`]] +[def __result_of_make_fused_procedure__ [link fusion.functional.generation.metafunctions.make_fused_procedure `make_fused_procedure`]] +[def __result_of_make_fused_function_object__ [link fusion.functional.generation.metafunctions.make_fused_function_object `make_fused_function_object`]] +[def __result_of_make_unfused_generic__ [link fusion.functional.generation.metafunctions.make_unfused_generic `make_unfused_generic`]] +[def __result_of_make_unfused_rvalue_args__ [link fusion.functional.generation.metafunctions.make_unfused_rvalue_args `make_unfused_rvalue_args`]] +[def __result_of_make_unfused_lvalue_args__ [link fusion.functional.generation.metafunctions.make_unfused_lvalue_args `make_unfused_lvalue_args`]] +[def __result_of_make_unfused_typed__ [link fusion.functional.generation.metafunctions.make_unfused_typed `make_unfused_typed`]] + [def __recursive_inline__ [link fusion.notes.recursive_inlined_functions Recursive Inlined Functions]] [def __overloaded_functions__ [link fusion.notes.overloaded_functions Overloaded Functions]] [def __tag_dispatching__ [link fusion.notes.tag_dispatching /tag dispatching/]] @@ -260,6 +301,7 @@ [include algorithms.qbk] [include tuples.qbk] [include extension.qbk] +[include functional.qbk] [include notes.qbk] [include changelog.qbk] [include acknowledgements.qbk]