From 6cbe04b95b7b973992477222e1052dd92eb44074 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Wed, 15 Feb 2012 00:42:56 +0000 Subject: [PATCH] Added Functional/OverloadedFunction source files. [SVN r77025] --- .../boost/functional/overloaded_function.hpp | 293 ++++++++++++++++++ .../functional/overloaded_function/config.hpp | 52 ++++ .../overloaded_function/detail/base.hpp | 85 +++++ .../detail/function_type.hpp | 73 +++++ 4 files changed, 503 insertions(+) create mode 100644 include/boost/functional/overloaded_function.hpp create mode 100644 include/boost/functional/overloaded_function/config.hpp create mode 100644 include/boost/functional/overloaded_function/detail/base.hpp create mode 100644 include/boost/functional/overloaded_function/detail/function_type.hpp diff --git a/include/boost/functional/overloaded_function.hpp b/include/boost/functional/overloaded_function.hpp new file mode 100644 index 0000000..a918e11 --- /dev/null +++ b/include/boost/functional/overloaded_function.hpp @@ -0,0 +1,293 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef DOXYGEN // Doxygen documentation only. + +#if !BOOST_PP_IS_ITERATING +# ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_ + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +#define BOOST_FUNCTIONAL_f_type(z, n, unused) \ + BOOST_PP_CAT(F, n) + +#define BOOST_FUNCTIONAL_f_arg(z, n, unused) \ + BOOST_PP_CAT(f, n) + +#define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_f_type(z, n, ~) \ + +#define BOOST_FUNCTIONAL_f_tparam_dflt(z, n, is_tspec) \ + BOOST_FUNCTIONAL_f_tparam(z, n, ~) \ + /* overload requires at least 2 functors so F0 and F1 not optional */ \ + BOOST_PP_EXPR_IIF(BOOST_PP_AND(BOOST_PP_NOT(is_tspec), \ + BOOST_PP_GREATER(n, 1)), \ + = void \ + ) + +#define BOOST_FUNCTIONAL_f_arg_decl(z, n, unused) \ + BOOST_FUNCTIONAL_f_type(z, n, ~) /* no qualifier to deduce tparam */ \ + BOOST_FUNCTIONAL_f_arg(z, n, ~) + +#define BOOST_FUNCTIONAL_g_type(z, n, unused) \ + BOOST_PP_CAT(G, n) + +#define BOOST_FUNCTIONAL_g_arg(z, n, unused) \ + BOOST_PP_CAT(g, n) + +#define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_g_type(z, n, ~) + +#define BOOST_FUNCTIONAL_g_arg_decl(z, n, unused) \ + BOOST_FUNCTIONAL_g_type(z, n, ~) /* no qualifier to deduce tparam */ \ + BOOST_FUNCTIONAL_g_arg(z, n, ~) + +#define BOOST_FUNCTIONAL_base(z, n, unused) \ + ::boost::overloaded_function_detail::base< \ + BOOST_FUNCTIONAL_f_type(z, n, ~) \ + > + +#define BOOST_FUNCTIONAL_inherit(z, n, unused) \ + public BOOST_FUNCTIONAL_base(z, n, ~) + +#define BOOST_FUNCTIONAL_base_init(z, n, unused) \ + BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~)) + +#define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \ + using BOOST_FUNCTIONAL_base(z, n, ~)::operator(); + +#define BOOST_FUNCTIONAL_function_type(z, n, unused) \ + typename ::boost::overloaded_function_detail::function_type< \ + BOOST_FUNCTIONAL_f_type(z, n, ~) \ + >::type + +namespace boost { + +// Iterate within namespace. +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_PP_SUB( /*at least 2 func to overload 2, 3, ...*/\ + BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, 2), \ + "boost/functional/overloaded_function.hpp")) +# include BOOST_PP_ITERATE() // Iterate over function arity. + +} // namespace + +#undef BOOST_FUNCTIONAL_f_type +#undef BOOST_FUNCTIONAL_f_arg +#undef BOOST_FUNCTIONAL_f_tparam +#undef BOOST_FUNCTIONAL_f_arg_decl +#undef BOOST_FUNCTIONAL_f_tparam_dflt +#undef BOOST_FUNCTIONAL_g_type +#undef BOOST_FUNCTIONAL_g_arg +#undef BOOST_FUNCTIONAL_g_tparam +#undef BOOST_FUNCTIONAL_g_arg_decl +#undef BOOST_FUNCTIONAL_base +#undef BOOST_FUNCTIONAL_inherit +#undef BOOST_FUNCTIONAL_base_init +#undef BOOST_FUNCTIONAL_using_operator_call +#undef BOOST_FUNCTIONAL_function_type + +# endif // #include guard + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# define BOOST_FUNCTIONAL_overloads \ + /* iterate as OVERLOADS, OVERLOADS-1, OVERLOADS-2, ... */ \ + BOOST_PP_SUB(BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \ + BOOST_PP_FRAME_ITERATION(1)) +# define BOOST_FUNCTIONAL_is_tspec \ + /* if template specialization */ \ + BOOST_PP_LESS(BOOST_FUNCTIONAL_overloads, \ + BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX) + +template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt, + BOOST_FUNCTIONAL_is_tspec) +> +class overloaded_function + // Template specialization. + BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), <) + BOOST_PP_IIF(BOOST_FUNCTIONAL_is_tspec, + BOOST_PP_ENUM + , + BOOST_PP_TUPLE_EAT(3) + )(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_type, ~) + BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), >) + // Bases (overloads >= 2 so always at least 2 bases). + : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_inherit, ~) +{ +public: + template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_g_tparam, ~) + > /* implicit */ inline overloaded_function( + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_g_arg_decl, ~)) + // Overloads >= 2 so always at least 2 bases to initialize. + : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_base_init, ~) + {} + + BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_using_operator_call, ~) +}; + +template< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~) +> +overloaded_function< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_function_type, ~) +> make_overloaded_function( + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg_decl, ~) +) { + return overloaded_function< + BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, + BOOST_FUNCTIONAL_function_type, ~) + >(BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg, ~)); +} + +# undef BOOST_FUNCTIONAL_overloads +# undef BOOST_FUNCTIONAL_is_tspec +#endif // iteration + +// DOCUMENTATION // + +#else // DOXYGEN + +/** @file +@brief Overload distinct function pointers, function references, and function +objects into a single function object. +*/ + +namespace boost { + +/** +@brief Function object to overload functions with distinct signatures. + +This function object aggregates together calls to functions of all the +specified function types F1, F2, etc. +The specified function types must have distinct parameters from one another and +they must be in the following format (which is the Boost.Function preferred +syntax): +@code + result_type (argument1_type, argumgnet2_type, ...) +@endcode + +In some cases, the @RefFunc{make_overloaded_function} function template can be +useful to construct the overloaded function object without explicitly +specifying the function types. + +The maximum number of functions to overload is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} +configuration macro. +The maximum number of function parameters for each of the specified function +types is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX} +configuration macro. + +@See + @RefSect{Tutorial} section, + @RefFunc{make_overloaded_function}, + @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}, + @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}, + Boost.Function. +*/ +template +class overloaded_function { +public: + /** + @brief Construct the overloaded function object. + + Any function pointer, function reference, and monomorphic function object + that can be converted to a boost::function function object can be + specified as parameter. + */ + overloaded_function(const boost::function&, + const boost::function&, ...); + + /** + @brief Call operator matching the signature of the function type specified + as 1st template parameter. + + This will in turn invoke the call operator of the 1st function passed to + the constructor. + */ + typename boost::function_traits::result_type operator()( + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type, + ...) const; + + /** + @brief Call operator matching the signature of the function type specified + as 2nd template parameter. + + This will in turn invoke the call operator of the 2nd function passed to + the constructor. + + @Note Similar call operators are present for all specified function types + F1, F2, etc (even if not exhaustively listed by this + documentation). + */ + typename boost::function_traits::result_type operator()( + typename boost::function_traits::arg1_type, + typename boost::function_traits::arg2_type, + ...) const; +}; + +/** +@brief Make an overloaded function object without explicitly specifying the +function types. + +This function template creates and returns an @RefClass{overloaded_function} +function object that overloads all the specified functions f1, +f2, etc. + +The function types are internally determined from the template parameter types +so they do not need to be explicitly specified. +Therefore, this function template usually has a more concise syntax when +compared with @RefClass{overloaded_function}. +This is especially useful when the explicit type of the returned +@RefClass{overloaded_function} does not need to be known (e.g., when used with Boost.Typeof's BOOST_AUTO (or C++11 auto) or when the overloaded +function object is handled using a function template parameter, see the +@RefSect{Tutorial} section). + +The maximum number of functions to overload is given by the +@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX} +configuration macro. + +@Note In this documentation, __function_type__ is a placeholder for a +symbol that is specific to implementation of this library. + +@See + @RefSect{Tutorial} section, + @RefClass{overloaded_function}, + @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}. +*/ +template +overloaded_function< + __function_type__, __function_type__, ... +> make_overloaded_function(F1 f1, F2 f2, ...); + +} // namespace + +#endif // DOXYGEN + diff --git a/include/boost/functional/overloaded_function/config.hpp b/include/boost/functional/overloaded_function/config.hpp new file mode 100644 index 0000000..17bd825 --- /dev/null +++ b/include/boost/functional/overloaded_function/config.hpp @@ -0,0 +1,52 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_HPP_ +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_HPP_ + +/** @file +@brief Change the compile-time configuration of this library. +*/ + +/** +@brief Specify the maximum number of arguments of the functions being +overloaded. + +If this macro is left undefined by the user, it has a default value of 5 +(increasing this number might increase compilation time). +When specified by the user, this macro must be a non-negative integer number. + +@See + @RefSectId{Getting_Started, Getting Started}, + @RefClass{boost::overloaded_function}. +*/ +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX 5 +#endif + +/** +@brief Specify the maximum number of functions that can be overloaded. + +If this macro is left undefined by the user, it has a default value of 5 +(increasing this number might increase compilation time). +When defined by the user, this macro must be an integer number greater or +equal than 2 (because at least two distinct functions need to be specified in +order to define an overload). + +@See + @RefSectId{Getting_Started, Getting Started}, + @RefClass{boost::overloaded_function}. +*/ +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX 5 +#endif +#if BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX < 2 +#error "BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX must be >= 2" +#endif + +#endif // #include guard + diff --git a/include/boost/functional/overloaded_function/detail/base.hpp b/include/boost/functional/overloaded_function/detail/base.hpp new file mode 100644 index 0000000..8c1d4bf --- /dev/null +++ b/include/boost/functional/overloaded_function/detail/base.hpp @@ -0,0 +1,85 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#if !BOOST_PP_IS_ITERATING +# ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_BASE_HPP_ +# define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_BASE_HPP_ + +# include +# include +# include +# include +# include +# include + +#define BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) \ + BOOST_PP_CAT(A, n) + +#define BOOST_FUNCTIONAL_DETAIL_arg_name(z, n, unused) \ + BOOST_PP_CAT(a, n) + +#define BOOST_FUNCTIONAL_DETAIL_arg_tparam(z, n, unused) \ + typename BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) + +#define BOOST_FUNCTIONAL_DETAIL_arg(z, n, unused) \ + BOOST_FUNCTIONAL_DETAIL_arg_type(z, n, unused) \ + BOOST_FUNCTIONAL_DETAIL_arg_name(z, n, unused) + +#define BOOST_FUNCTIONAL_DETAIL_f \ + R (BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, \ + BOOST_FUNCTIONAL_DETAIL_arg_type, ~)) + +namespace boost { namespace overloaded_function_detail { + +template +class base {}; // Empty template cannot be used directly (only its spec). + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX, \ + "boost/functional/overloaded_function/detail/base.hpp")) +# include BOOST_PP_ITERATE() // Iterate over funciton arity. + +} } // namespace + +#undef BOOST_FUNCTIONAL_DETAIL_arg_type +#undef BOOST_FUNCTIONAL_DETAIL_arg_name +#undef BOOST_FUNCTIONAL_DETAIL_arg_tparam +#undef BOOST_FUNCTIONAL_DETAIL_arg +#undef BOOST_FUNCTIONAL_DETAIL_f + +# endif // #include guard + +#elif BOOST_PP_ITERATION_DEPTH() == 1 +# define BOOST_FUNCTIONAL_DETAIL_arity BOOST_PP_FRAME_ITERATION(1) + +template< + typename R + BOOST_PP_COMMA_IF(BOOST_FUNCTIONAL_DETAIL_arity) + BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg_tparam, ~) +> +class base< BOOST_FUNCTIONAL_DETAIL_f > { +public: + /* implicit */ inline base( + // This requires specified type to be implicitly convertible to + // a boost::function<> functor. + boost::function< BOOST_FUNCTIONAL_DETAIL_f > const& f): f_(f) + {} + + inline R operator()(BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg, ~)) const { + return f_(BOOST_PP_ENUM(BOOST_FUNCTIONAL_DETAIL_arity, + BOOST_FUNCTIONAL_DETAIL_arg_name, ~)); + } + +private: + boost::function< BOOST_FUNCTIONAL_DETAIL_f > const f_; +}; + +# undef BOOST_FUNCTIONAL_DETAIL_arity +#endif // iteration + diff --git a/include/boost/functional/overloaded_function/detail/function_type.hpp b/include/boost/functional/overloaded_function/detail/function_type.hpp new file mode 100644 index 0000000..31f83a7 --- /dev/null +++ b/include/boost/functional/overloaded_function/detail/function_type.hpp @@ -0,0 +1,73 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/functional/overloaded_function + +#ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_FUNCTION_TYPE_HPP_ +#define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_DETAIL_FUNCTION_TYPE_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace overloaded_function_detail { + +// Requires: F is a monomorphic functor (i.e., has non-template `operator()`). +// Returns: F's function type `result_type (arg1_type, arg2_type, ...)`. +// It does not assume F typedef result_type, arg1_type, ... but needs typeof. +template +class functor_type { + typedef BOOST_TYPEOF_TPL(&(F::operator())) call_ptr; +public: + typedef + typename boost::function_types::function_type< + typename boost::mpl::push_front< + typename boost::mpl::pop_front< // Remove functor type (1st). + typename boost::function_types::parameter_types< + call_ptr>::type + >::type + , typename boost::function_types::result_type::type + >::type + >::type + type; +}; + +// Requires: F is a function type, pointer, reference, or monomorphic functor. +// Returns: F's function type `result_type (arg1_type, arg2_type, ...)`. +template +struct function_type { + typedef + typename boost::mpl::if_, + boost::mpl::identity + , + typename boost::mpl::if_, + boost::remove_pointer + , + typename boost::mpl::if_, + boost::remove_reference + , // Requires, it's a functor. + functor_type + >::type + >::type + >::type + ::type type; +}; + +} } // namespace + +#endif // #include guard +