2 // Copyright (C) 2009-2012 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0
4 // (see accompanying file LICENSE_1_0.txt or a copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 // Home at http://www.boost.org/libs/functional/overloaded_function
8 #ifndef DOXYGEN // Doxygen documentation only.
10 #if !BOOST_PP_IS_ITERATING
11 # ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
12 # define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
14 # include <boost/functional/overloaded_function/detail/base.hpp>
15 # include <boost/functional/overloaded_function/detail/function_type.hpp>
16 # include <boost/functional/overloaded_function/config.hpp>
17 # include <boost/typeof/typeof.hpp>
18 # include <boost/preprocessor/iteration/iterate.hpp>
19 # include <boost/preprocessor/repetition/enum.hpp>
20 # include <boost/preprocessor/repetition/repeat.hpp>
21 # include <boost/preprocessor/control/expr_iif.hpp>
22 # include <boost/preprocessor/control/expr_if.hpp>
23 # include <boost/preprocessor/comparison/greater.hpp>
24 # include <boost/preprocessor/comparison/less.hpp>
25 # include <boost/preprocessor/cat.hpp>
26 # include <boost/preprocessor/arithmetic/add.hpp>
27 # include <boost/preprocessor/arithmetic/sub.hpp>
28 # include <boost/preprocessor/tuple/eat.hpp>
29 # include <boost/preprocessor/logical/and.hpp>
30 # include <boost/preprocessor/logical/not.hpp>
31 # include <boost/preprocessor/facilities/expand.hpp>
33 #define BOOST_FUNCTIONAL_f_type(z, n, unused) \
36 #define BOOST_FUNCTIONAL_f_arg(z, n, unused) \
39 #define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \
40 typename BOOST_FUNCTIONAL_f_type(z, n, ~) \
42 #define BOOST_FUNCTIONAL_f_tparam_dflt(z, n, is_tspec) \
43 BOOST_FUNCTIONAL_f_tparam(z, n, ~) \
44 /* overload requires at least 2 functors so F0 and F1 not optional */ \
45 BOOST_PP_EXPR_IIF(BOOST_PP_AND(BOOST_PP_NOT(is_tspec), \
46 BOOST_PP_GREATER(n, 1)), \
50 #define BOOST_FUNCTIONAL_f_arg_decl(z, n, unused) \
51 BOOST_FUNCTIONAL_f_type(z, n, ~) /* no qualifier to deduce tparam */ \
52 BOOST_FUNCTIONAL_f_arg(z, n, ~)
54 #define BOOST_FUNCTIONAL_g_type(z, n, unused) \
57 #define BOOST_FUNCTIONAL_g_arg(z, n, unused) \
60 #define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \
61 typename BOOST_FUNCTIONAL_g_type(z, n, ~)
63 #define BOOST_FUNCTIONAL_g_arg_decl(z, n, unused) \
64 BOOST_FUNCTIONAL_g_type(z, n, ~) /* no qualifier to deduce tparam */ \
65 BOOST_FUNCTIONAL_g_arg(z, n, ~)
67 #define BOOST_FUNCTIONAL_base(z, n, unused) \
68 ::boost::overloaded_function_detail::base< \
69 BOOST_FUNCTIONAL_f_type(z, n, ~) \
72 #define BOOST_FUNCTIONAL_inherit(z, n, unused) \
73 public BOOST_FUNCTIONAL_base(z, n, ~)
75 #define BOOST_FUNCTIONAL_base_init(z, n, unused) \
76 BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~))
78 #define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \
79 using BOOST_FUNCTIONAL_base(z, n, ~)::operator();
81 #define BOOST_FUNCTIONAL_function_type(z, n, unused) \
82 typename ::boost::overloaded_function_detail::function_type< \
83 BOOST_FUNCTIONAL_f_type(z, n, ~) \
86 # define BOOST_PP_ITERATION_PARAMS_1 \
87 /* at least 2 func to overload so start from 2 to MAX */ \
88 /* (cannot iterate [0, MAX-2) because error on Sun) */ \
89 (3, (2, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \
90 "boost/functional/overloaded_function.hpp"))
91 # include BOOST_PP_ITERATE() // Iterate over function arity.
93 #undef BOOST_FUNCTIONAL_f_type
94 #undef BOOST_FUNCTIONAL_f_arg
95 #undef BOOST_FUNCTIONAL_f_tparam
96 #undef BOOST_FUNCTIONAL_f_arg_decl
97 #undef BOOST_FUNCTIONAL_f_tparam_dflt
98 #undef BOOST_FUNCTIONAL_g_type
99 #undef BOOST_FUNCTIONAL_g_arg
100 #undef BOOST_FUNCTIONAL_g_tparam
101 #undef BOOST_FUNCTIONAL_g_arg_decl
102 #undef BOOST_FUNCTIONAL_base
103 #undef BOOST_FUNCTIONAL_inherit
104 #undef BOOST_FUNCTIONAL_base_init
105 #undef BOOST_FUNCTIONAL_using_operator_call
106 #undef BOOST_FUNCTIONAL_function_type
108 # endif // #include guard
110 #elif BOOST_PP_ITERATION_DEPTH() == 1
111 # define BOOST_FUNCTIONAL_overloads \
112 /* iterate as OVERLOADS, OVERLOADS-1, OVERLOADS-2, ... */ \
113 /* (add 2 because iteration started from 2 to MAX) */ \
114 BOOST_PP_ADD(2, BOOST_PP_SUB( \
115 BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \
116 BOOST_PP_FRAME_ITERATION(1)))
117 # define BOOST_FUNCTIONAL_is_tspec \
118 /* if template specialization */ \
119 BOOST_PP_LESS(BOOST_FUNCTIONAL_overloads, \
120 BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX)
122 // For type-of emulation: This must be included at this pp iteration level.
123 # include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
128 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt,
129 BOOST_FUNCTIONAL_is_tspec)
131 class overloaded_function
132 // Template specialization.
133 BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), <)
134 BOOST_PP_IIF(BOOST_FUNCTIONAL_is_tspec,
137 BOOST_PP_TUPLE_EAT(3)
138 )(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_type, ~)
139 BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), >)
140 // Bases (overloads >= 2 so always at least 2 bases).
141 : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
142 BOOST_FUNCTIONAL_inherit, ~)
146 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_g_tparam, ~)
147 > /* implicit */ inline overloaded_function(
148 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
149 BOOST_FUNCTIONAL_g_arg_decl, ~))
150 // Overloads >= 2 so always at least 2 bases to initialize.
151 : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
152 BOOST_FUNCTIONAL_base_init, ~)
155 BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads,
156 BOOST_FUNCTIONAL_using_operator_call, ~)
160 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~)
163 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_function_type, ~)
164 > make_overloaded_function(
165 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg_decl, ~)
167 return overloaded_function<
168 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
169 BOOST_FUNCTIONAL_function_type, ~)
170 >(BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg, ~));
175 // For type-of emulation: Register overloaded function type (for _AUTO, etc).
176 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::overloaded_function,
177 BOOST_FUNCTIONAL_overloads)
179 # undef BOOST_FUNCTIONAL_overloads
180 # undef BOOST_FUNCTIONAL_is_tspec
188 @brief Overload distinct function pointers, function references, and
189 monomorphic function objects into a single function object.
195 @brief Function object to overload functions with distinct signatures.
197 This function object aggregates together calls to functions of all the
198 specified function types <c>F1</c>, <c>F2</c>, etc which must have distinct
199 function signatures from one another.
203 Each function type must be specified using the following syntax (which is
204 Boost.Function's preferred syntax):
206 result_type (argument1_type\, argumgnet2_type\, ...)
211 In some cases, the @RefFunc{make_overloaded_function} function template can be
212 useful to construct an overloaded function object without explicitly
213 specifying the function types.
215 At least two distinct function types must be specified (because there is
216 nothing to overload between one or zero functions).
217 The maximum number of functions to overload is given by the
218 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
220 The maximum number of function parameters for each of the specified function
221 types is given by the
222 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}
225 @See @RefSect{tutorial, Tutorial} section, @RefFunc{make_overloaded_function},
226 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX},
227 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX},
230 template<typename F1, typename F2, ...>
231 class overloaded_function {
234 @brief Construct the overloaded function object.
236 Any function pointer, function reference, and monomorphic function object
237 that can be converted to a <c>boost::function</c> function object can be
238 specified as parameter.
240 @Note Unfortunately, it is not possible to support polymorphic function
241 objects (as explained <a
242 href="http://lists.boost.org/Archives/boost/2012/03/191744.php">here</a>).
244 overloaded_function(const boost::function<F1>&,
245 const boost::function<F2>&, ...);
248 @brief Call operator matching the signature of the function type specified
249 as 1st template parameter.
251 This will in turn invoke the call operator of the 1st function passed to
254 typename boost::function_traits<F1>::result_type operator()(
255 typename boost::function_traits<F1>::arg1_type,
256 typename boost::function_traits<F1>::arg2_type,
260 @brief Call operator matching the signature of the function type specified
261 as 2nd template parameter.
263 This will in turn invoke the call operator of the 2nd function passed to
266 @Note Similar call operators are present for all specified function types
267 <c>F1</c>, <c>F2</c>, etc (even if not exhaustively listed by this
270 typename boost::function_traits<F2>::result_type operator()(
271 typename boost::function_traits<F2>::arg1_type,
272 typename boost::function_traits<F2>::arg2_type,
277 @brief Make an overloaded function object without explicitly specifying the
280 This function template creates and returns an @RefClass{overloaded_function}
281 object that overloads all the specified functions <c>f1</c>, <c>f2</c>, etc.
283 The function types are internally determined from the template parameter types
284 so they do not need to be explicitly specified.
285 Therefore, this function template usually has a more concise syntax when
286 compared with @RefClass{overloaded_function}.
287 This is especially useful when the explicit type of the returned
288 @RefClass{overloaded_function} object does not need to be known (e.g., when
289 used with Boost.Typeof's <c>BOOST_AUTO</c>, C++11 <c>auto</c>, or when the
290 overloaded function object is handled using a function template parameter, see
291 the @RefSect{tutorial, Tutorial} section).
293 The maximum number of functions to overload is given by the
294 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
297 @Note In this documentation, <c>__function_type__</c> is a placeholder for a
298 symbol that is specific to the implementation of this library.
300 @See @RefSect{tutorial, Tutorial} section, @RefClass{overloaded_function},
301 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}.
303 template<typename F1, typename F2, ...>
305 __function_type__<F1>, __function_type__<F2>, ...
306 > make_overloaded_function(F1 f1, F2 f2, ...);