Chris@16: Chris@16: // Copyright (C) 2009-2012 Lorenzo Caminiti Chris@16: // Distributed under the Boost Software License, Version 1.0 Chris@16: // (see accompanying file LICENSE_1_0.txt or a copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Home at http://www.boost.org/libs/functional/overloaded_function Chris@16: Chris@16: #ifndef DOXYGEN // Doxygen documentation only. Chris@16: Chris@16: #if !BOOST_PP_IS_ITERATING Chris@16: # ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ Chris@16: # define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: #define BOOST_FUNCTIONAL_f_type(z, n, unused) \ Chris@16: BOOST_PP_CAT(F, n) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_f_arg(z, n, unused) \ Chris@16: BOOST_PP_CAT(f, n) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \ Chris@16: typename BOOST_FUNCTIONAL_f_type(z, n, ~) \ Chris@16: Chris@16: #define BOOST_FUNCTIONAL_f_tparam_dflt(z, n, is_tspec) \ Chris@16: BOOST_FUNCTIONAL_f_tparam(z, n, ~) \ Chris@16: /* overload requires at least 2 functors so F0 and F1 not optional */ \ Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_AND(BOOST_PP_NOT(is_tspec), \ Chris@16: BOOST_PP_GREATER(n, 1)), \ Chris@16: = void \ Chris@16: ) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_f_arg_decl(z, n, unused) \ Chris@16: BOOST_FUNCTIONAL_f_type(z, n, ~) /* no qualifier to deduce tparam */ \ Chris@16: BOOST_FUNCTIONAL_f_arg(z, n, ~) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_g_type(z, n, unused) \ Chris@16: BOOST_PP_CAT(G, n) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_g_arg(z, n, unused) \ Chris@16: BOOST_PP_CAT(g, n) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \ Chris@16: typename BOOST_FUNCTIONAL_g_type(z, n, ~) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_g_arg_decl(z, n, unused) \ Chris@16: BOOST_FUNCTIONAL_g_type(z, n, ~) /* no qualifier to deduce tparam */ \ Chris@16: BOOST_FUNCTIONAL_g_arg(z, n, ~) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_base(z, n, unused) \ Chris@16: ::boost::overloaded_function_detail::base< \ Chris@16: BOOST_FUNCTIONAL_f_type(z, n, ~) \ Chris@16: > Chris@16: Chris@16: #define BOOST_FUNCTIONAL_inherit(z, n, unused) \ Chris@16: public BOOST_FUNCTIONAL_base(z, n, ~) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_base_init(z, n, unused) \ Chris@16: BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~)) Chris@16: Chris@16: #define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \ Chris@16: using BOOST_FUNCTIONAL_base(z, n, ~)::operator(); Chris@16: Chris@16: #define BOOST_FUNCTIONAL_function_type(z, n, unused) \ Chris@16: typename ::boost::overloaded_function_detail::function_type< \ Chris@16: BOOST_FUNCTIONAL_f_type(z, n, ~) \ Chris@16: >::type Chris@16: Chris@16: # define BOOST_PP_ITERATION_PARAMS_1 \ Chris@16: /* at least 2 func to overload so start from 2 to MAX */ \ Chris@16: /* (cannot iterate [0, MAX-2) because error on Sun) */ \ Chris@16: (3, (2, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \ Chris@16: "boost/functional/overloaded_function.hpp")) Chris@16: # include BOOST_PP_ITERATE() // Iterate over function arity. Chris@16: Chris@16: #undef BOOST_FUNCTIONAL_f_type Chris@16: #undef BOOST_FUNCTIONAL_f_arg Chris@16: #undef BOOST_FUNCTIONAL_f_tparam Chris@16: #undef BOOST_FUNCTIONAL_f_arg_decl Chris@16: #undef BOOST_FUNCTIONAL_f_tparam_dflt Chris@16: #undef BOOST_FUNCTIONAL_g_type Chris@16: #undef BOOST_FUNCTIONAL_g_arg Chris@16: #undef BOOST_FUNCTIONAL_g_tparam Chris@16: #undef BOOST_FUNCTIONAL_g_arg_decl Chris@16: #undef BOOST_FUNCTIONAL_base Chris@16: #undef BOOST_FUNCTIONAL_inherit Chris@16: #undef BOOST_FUNCTIONAL_base_init Chris@16: #undef BOOST_FUNCTIONAL_using_operator_call Chris@16: #undef BOOST_FUNCTIONAL_function_type Chris@16: Chris@16: # endif // #include guard Chris@16: Chris@16: #elif BOOST_PP_ITERATION_DEPTH() == 1 Chris@16: # define BOOST_FUNCTIONAL_overloads \ Chris@16: /* iterate as OVERLOADS, OVERLOADS-1, OVERLOADS-2, ... */ \ Chris@16: /* (add 2 because iteration started from 2 to MAX) */ \ Chris@16: BOOST_PP_ADD(2, BOOST_PP_SUB( \ Chris@16: BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \ Chris@16: BOOST_PP_FRAME_ITERATION(1))) Chris@16: # define BOOST_FUNCTIONAL_is_tspec \ Chris@16: /* if template specialization */ \ Chris@16: BOOST_PP_LESS(BOOST_FUNCTIONAL_overloads, \ Chris@16: BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX) Chris@16: Chris@16: // For type-of emulation: This must be included at this pp iteration level. Chris@16: # include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: template< Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt, Chris@16: BOOST_FUNCTIONAL_is_tspec) Chris@16: > Chris@16: class overloaded_function Chris@16: // Template specialization. Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), <) Chris@16: BOOST_PP_IIF(BOOST_FUNCTIONAL_is_tspec, Chris@16: BOOST_PP_ENUM Chris@16: , Chris@16: BOOST_PP_TUPLE_EAT(3) Chris@16: )(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_type, ~) Chris@16: BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), >) Chris@16: // Bases (overloads >= 2 so always at least 2 bases). Chris@16: : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, Chris@16: BOOST_FUNCTIONAL_inherit, ~) Chris@16: { Chris@16: public: Chris@16: template< Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_g_tparam, ~) Chris@16: > /* implicit */ inline overloaded_function( Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, Chris@16: BOOST_FUNCTIONAL_g_arg_decl, ~)) Chris@16: // Overloads >= 2 so always at least 2 bases to initialize. Chris@16: : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, Chris@16: BOOST_FUNCTIONAL_base_init, ~) Chris@16: {} Chris@16: Chris@16: BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads, Chris@16: BOOST_FUNCTIONAL_using_operator_call, ~) Chris@16: }; Chris@16: Chris@16: template< Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~) Chris@16: > Chris@16: overloaded_function< Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_function_type, ~) Chris@16: > make_overloaded_function( Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg_decl, ~) Chris@16: ) { Chris@16: return overloaded_function< Chris@16: BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, Chris@16: BOOST_FUNCTIONAL_function_type, ~) Chris@16: >(BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg, ~)); Chris@16: } Chris@16: Chris@16: } // namespace Chris@16: Chris@16: // For type-of emulation: Register overloaded function type (for _AUTO, etc). Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(boost::overloaded_function, Chris@16: BOOST_FUNCTIONAL_overloads) Chris@16: Chris@16: # undef BOOST_FUNCTIONAL_overloads Chris@16: # undef BOOST_FUNCTIONAL_is_tspec Chris@16: #endif // iteration Chris@16: Chris@16: // DOCUMENTATION // Chris@16: Chris@16: #else // DOXYGEN Chris@16: Chris@16: /** @file Chris@16: @brief Overload distinct function pointers, function references, and Chris@16: monomorphic function objects into a single function object. Chris@16: */ Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: /** Chris@16: @brief Function object to overload functions with distinct signatures. Chris@16: Chris@16: This function object aggregates together calls to functions of all the Chris@16: specified function types F1, F2, etc which must have distinct Chris@16: function signatures from one another. Chris@16: Chris@16: @Params Chris@16: @Param{Fi, Chris@16: Each function type must be specified using the following syntax (which is Chris@16: Boost.Function's preferred syntax): Chris@16: @code Chris@16: result_type (argument1_type\, argumgnet2_type\, ...) Chris@16: @endcode Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: In some cases, the @RefFunc{make_overloaded_function} function template can be Chris@16: useful to construct an overloaded function object without explicitly Chris@16: specifying the function types. Chris@16: Chris@16: At least two distinct function types must be specified (because there is Chris@16: nothing to overload between one or zero functions). Chris@16: The maximum number of functions to overload is given by the Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} Chris@16: configuration macro. Chris@16: The maximum number of function parameters for each of the specified function Chris@16: types is given by the Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX} Chris@16: configuration macro. Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, @RefFunc{make_overloaded_function}, Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}, Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}, Chris@16: Boost.Function. Chris@16: */ Chris@16: template Chris@16: class overloaded_function { Chris@16: public: Chris@16: /** Chris@16: @brief Construct the overloaded function object. Chris@16: Chris@16: Any function pointer, function reference, and monomorphic function object Chris@16: that can be converted to a boost::function function object can be Chris@16: specified as parameter. Chris@16: Chris@16: @Note Unfortunately, it is not possible to support polymorphic function Chris@16: objects (as explained here). Chris@16: */ Chris@16: overloaded_function(const boost::function&, Chris@16: const boost::function&, ...); Chris@16: Chris@16: /** Chris@16: @brief Call operator matching the signature of the function type specified Chris@16: as 1st template parameter. Chris@16: Chris@16: This will in turn invoke the call operator of the 1st function passed to Chris@16: the constructor. Chris@16: */ Chris@16: typename boost::function_traits::result_type operator()( Chris@16: typename boost::function_traits::arg1_type, Chris@16: typename boost::function_traits::arg2_type, Chris@16: ...) const; Chris@16: Chris@16: /** Chris@16: @brief Call operator matching the signature of the function type specified Chris@16: as 2nd template parameter. Chris@16: Chris@16: This will in turn invoke the call operator of the 2nd function passed to Chris@16: the constructor. Chris@16: Chris@16: @Note Similar call operators are present for all specified function types Chris@16: F1, F2, etc (even if not exhaustively listed by this Chris@16: documentation). Chris@16: */ Chris@16: typename boost::function_traits::result_type operator()( Chris@16: typename boost::function_traits::arg1_type, Chris@16: typename boost::function_traits::arg2_type, Chris@16: ...) const; Chris@16: }; Chris@16: Chris@16: /** Chris@16: @brief Make an overloaded function object without explicitly specifying the Chris@16: function types. Chris@16: Chris@16: This function template creates and returns an @RefClass{overloaded_function} Chris@16: object that overloads all the specified functions f1, f2, etc. Chris@16: Chris@16: The function types are internally determined from the template parameter types Chris@16: so they do not need to be explicitly specified. Chris@16: Therefore, this function template usually has a more concise syntax when Chris@16: compared with @RefClass{overloaded_function}. Chris@16: This is especially useful when the explicit type of the returned Chris@16: @RefClass{overloaded_function} object does not need to be known (e.g., when Chris@16: used with Boost.Typeof's BOOST_AUTO, C++11 auto, or when the Chris@16: overloaded function object is handled using a function template parameter, see Chris@16: the @RefSect{tutorial, Tutorial} section). Chris@16: Chris@16: The maximum number of functions to overload is given by the Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} Chris@16: configuration macro. Chris@16: Chris@16: @Note In this documentation, __function_type__ is a placeholder for a Chris@16: symbol that is specific to the implementation of this library. Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, @RefClass{overloaded_function}, Chris@16: @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}. Chris@16: */ Chris@16: template Chris@16: overloaded_function< Chris@16: __function_type__, __function_type__, ... Chris@16: > make_overloaded_function(F1 f1, F2 f2, ...); Chris@16: Chris@16: } // namespace Chris@16: Chris@16: #endif // DOXYGEN Chris@16: