Chris@16
|
1
|
Chris@16
|
2 // Copyright (C) 2009-2012 Lorenzo Caminiti
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0
|
Chris@16
|
4 // (see accompanying file LICENSE_1_0.txt or a copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 // Home at http://www.boost.org/libs/functional/overloaded_function
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef DOXYGEN // Doxygen documentation only.
|
Chris@16
|
9
|
Chris@16
|
10 #if !BOOST_PP_IS_ITERATING
|
Chris@16
|
11 # ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
|
Chris@16
|
12 # define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
|
Chris@16
|
13
|
Chris@16
|
14 # include <boost/functional/overloaded_function/detail/base.hpp>
|
Chris@16
|
15 # include <boost/functional/overloaded_function/detail/function_type.hpp>
|
Chris@16
|
16 # include <boost/functional/overloaded_function/config.hpp>
|
Chris@16
|
17 # include <boost/typeof/typeof.hpp>
|
Chris@16
|
18 # include <boost/preprocessor/iteration/iterate.hpp>
|
Chris@16
|
19 # include <boost/preprocessor/repetition/enum.hpp>
|
Chris@16
|
20 # include <boost/preprocessor/repetition/repeat.hpp>
|
Chris@16
|
21 # include <boost/preprocessor/control/expr_iif.hpp>
|
Chris@16
|
22 # include <boost/preprocessor/control/expr_if.hpp>
|
Chris@16
|
23 # include <boost/preprocessor/comparison/greater.hpp>
|
Chris@16
|
24 # include <boost/preprocessor/comparison/less.hpp>
|
Chris@16
|
25 # include <boost/preprocessor/cat.hpp>
|
Chris@16
|
26 # include <boost/preprocessor/arithmetic/add.hpp>
|
Chris@16
|
27 # include <boost/preprocessor/arithmetic/sub.hpp>
|
Chris@16
|
28 # include <boost/preprocessor/tuple/eat.hpp>
|
Chris@16
|
29 # include <boost/preprocessor/logical/and.hpp>
|
Chris@16
|
30 # include <boost/preprocessor/logical/not.hpp>
|
Chris@16
|
31 # include <boost/preprocessor/facilities/expand.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #define BOOST_FUNCTIONAL_f_type(z, n, unused) \
|
Chris@16
|
34 BOOST_PP_CAT(F, n)
|
Chris@16
|
35
|
Chris@16
|
36 #define BOOST_FUNCTIONAL_f_arg(z, n, unused) \
|
Chris@16
|
37 BOOST_PP_CAT(f, n)
|
Chris@16
|
38
|
Chris@16
|
39 #define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \
|
Chris@16
|
40 typename BOOST_FUNCTIONAL_f_type(z, n, ~) \
|
Chris@16
|
41
|
Chris@16
|
42 #define BOOST_FUNCTIONAL_f_tparam_dflt(z, n, is_tspec) \
|
Chris@16
|
43 BOOST_FUNCTIONAL_f_tparam(z, n, ~) \
|
Chris@16
|
44 /* overload requires at least 2 functors so F0 and F1 not optional */ \
|
Chris@16
|
45 BOOST_PP_EXPR_IIF(BOOST_PP_AND(BOOST_PP_NOT(is_tspec), \
|
Chris@16
|
46 BOOST_PP_GREATER(n, 1)), \
|
Chris@16
|
47 = void \
|
Chris@16
|
48 )
|
Chris@16
|
49
|
Chris@16
|
50 #define BOOST_FUNCTIONAL_f_arg_decl(z, n, unused) \
|
Chris@16
|
51 BOOST_FUNCTIONAL_f_type(z, n, ~) /* no qualifier to deduce tparam */ \
|
Chris@16
|
52 BOOST_FUNCTIONAL_f_arg(z, n, ~)
|
Chris@16
|
53
|
Chris@16
|
54 #define BOOST_FUNCTIONAL_g_type(z, n, unused) \
|
Chris@16
|
55 BOOST_PP_CAT(G, n)
|
Chris@16
|
56
|
Chris@16
|
57 #define BOOST_FUNCTIONAL_g_arg(z, n, unused) \
|
Chris@16
|
58 BOOST_PP_CAT(g, n)
|
Chris@16
|
59
|
Chris@16
|
60 #define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \
|
Chris@16
|
61 typename BOOST_FUNCTIONAL_g_type(z, n, ~)
|
Chris@16
|
62
|
Chris@16
|
63 #define BOOST_FUNCTIONAL_g_arg_decl(z, n, unused) \
|
Chris@16
|
64 BOOST_FUNCTIONAL_g_type(z, n, ~) /* no qualifier to deduce tparam */ \
|
Chris@16
|
65 BOOST_FUNCTIONAL_g_arg(z, n, ~)
|
Chris@16
|
66
|
Chris@16
|
67 #define BOOST_FUNCTIONAL_base(z, n, unused) \
|
Chris@16
|
68 ::boost::overloaded_function_detail::base< \
|
Chris@16
|
69 BOOST_FUNCTIONAL_f_type(z, n, ~) \
|
Chris@16
|
70 >
|
Chris@16
|
71
|
Chris@16
|
72 #define BOOST_FUNCTIONAL_inherit(z, n, unused) \
|
Chris@16
|
73 public BOOST_FUNCTIONAL_base(z, n, ~)
|
Chris@16
|
74
|
Chris@16
|
75 #define BOOST_FUNCTIONAL_base_init(z, n, unused) \
|
Chris@16
|
76 BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~))
|
Chris@16
|
77
|
Chris@16
|
78 #define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \
|
Chris@16
|
79 using BOOST_FUNCTIONAL_base(z, n, ~)::operator();
|
Chris@16
|
80
|
Chris@16
|
81 #define BOOST_FUNCTIONAL_function_type(z, n, unused) \
|
Chris@16
|
82 typename ::boost::overloaded_function_detail::function_type< \
|
Chris@16
|
83 BOOST_FUNCTIONAL_f_type(z, n, ~) \
|
Chris@16
|
84 >::type
|
Chris@16
|
85
|
Chris@16
|
86 # define BOOST_PP_ITERATION_PARAMS_1 \
|
Chris@16
|
87 /* at least 2 func to overload so start from 2 to MAX */ \
|
Chris@16
|
88 /* (cannot iterate [0, MAX-2) because error on Sun) */ \
|
Chris@16
|
89 (3, (2, BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \
|
Chris@16
|
90 "boost/functional/overloaded_function.hpp"))
|
Chris@16
|
91 # include BOOST_PP_ITERATE() // Iterate over function arity.
|
Chris@16
|
92
|
Chris@16
|
93 #undef BOOST_FUNCTIONAL_f_type
|
Chris@16
|
94 #undef BOOST_FUNCTIONAL_f_arg
|
Chris@16
|
95 #undef BOOST_FUNCTIONAL_f_tparam
|
Chris@16
|
96 #undef BOOST_FUNCTIONAL_f_arg_decl
|
Chris@16
|
97 #undef BOOST_FUNCTIONAL_f_tparam_dflt
|
Chris@16
|
98 #undef BOOST_FUNCTIONAL_g_type
|
Chris@16
|
99 #undef BOOST_FUNCTIONAL_g_arg
|
Chris@16
|
100 #undef BOOST_FUNCTIONAL_g_tparam
|
Chris@16
|
101 #undef BOOST_FUNCTIONAL_g_arg_decl
|
Chris@16
|
102 #undef BOOST_FUNCTIONAL_base
|
Chris@16
|
103 #undef BOOST_FUNCTIONAL_inherit
|
Chris@16
|
104 #undef BOOST_FUNCTIONAL_base_init
|
Chris@16
|
105 #undef BOOST_FUNCTIONAL_using_operator_call
|
Chris@16
|
106 #undef BOOST_FUNCTIONAL_function_type
|
Chris@16
|
107
|
Chris@16
|
108 # endif // #include guard
|
Chris@16
|
109
|
Chris@16
|
110 #elif BOOST_PP_ITERATION_DEPTH() == 1
|
Chris@16
|
111 # define BOOST_FUNCTIONAL_overloads \
|
Chris@16
|
112 /* iterate as OVERLOADS, OVERLOADS-1, OVERLOADS-2, ... */ \
|
Chris@16
|
113 /* (add 2 because iteration started from 2 to MAX) */ \
|
Chris@16
|
114 BOOST_PP_ADD(2, BOOST_PP_SUB( \
|
Chris@16
|
115 BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX, \
|
Chris@16
|
116 BOOST_PP_FRAME_ITERATION(1)))
|
Chris@16
|
117 # define BOOST_FUNCTIONAL_is_tspec \
|
Chris@16
|
118 /* if template specialization */ \
|
Chris@16
|
119 BOOST_PP_LESS(BOOST_FUNCTIONAL_overloads, \
|
Chris@16
|
120 BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX)
|
Chris@16
|
121
|
Chris@16
|
122 // For type-of emulation: This must be included at this pp iteration level.
|
Chris@16
|
123 # include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
|
Chris@16
|
124
|
Chris@16
|
125 namespace boost {
|
Chris@16
|
126
|
Chris@16
|
127 template<
|
Chris@16
|
128 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt,
|
Chris@16
|
129 BOOST_FUNCTIONAL_is_tspec)
|
Chris@16
|
130 >
|
Chris@16
|
131 class overloaded_function
|
Chris@16
|
132 // Template specialization.
|
Chris@16
|
133 BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), <)
|
Chris@16
|
134 BOOST_PP_IIF(BOOST_FUNCTIONAL_is_tspec,
|
Chris@16
|
135 BOOST_PP_ENUM
|
Chris@16
|
136 ,
|
Chris@16
|
137 BOOST_PP_TUPLE_EAT(3)
|
Chris@16
|
138 )(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_type, ~)
|
Chris@16
|
139 BOOST_PP_EXPR_IIF(BOOST_PP_EXPAND(BOOST_FUNCTIONAL_is_tspec), >)
|
Chris@16
|
140 // Bases (overloads >= 2 so always at least 2 bases).
|
Chris@16
|
141 : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
|
Chris@16
|
142 BOOST_FUNCTIONAL_inherit, ~)
|
Chris@16
|
143 {
|
Chris@16
|
144 public:
|
Chris@16
|
145 template<
|
Chris@16
|
146 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_g_tparam, ~)
|
Chris@16
|
147 > /* implicit */ inline overloaded_function(
|
Chris@16
|
148 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
|
Chris@16
|
149 BOOST_FUNCTIONAL_g_arg_decl, ~))
|
Chris@16
|
150 // Overloads >= 2 so always at least 2 bases to initialize.
|
Chris@16
|
151 : BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
|
Chris@16
|
152 BOOST_FUNCTIONAL_base_init, ~)
|
Chris@16
|
153 {}
|
Chris@16
|
154
|
Chris@16
|
155 BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads,
|
Chris@16
|
156 BOOST_FUNCTIONAL_using_operator_call, ~)
|
Chris@16
|
157 };
|
Chris@16
|
158
|
Chris@16
|
159 template<
|
Chris@16
|
160 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~)
|
Chris@16
|
161 >
|
Chris@16
|
162 overloaded_function<
|
Chris@16
|
163 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_function_type, ~)
|
Chris@16
|
164 > make_overloaded_function(
|
Chris@16
|
165 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg_decl, ~)
|
Chris@16
|
166 ) {
|
Chris@16
|
167 return overloaded_function<
|
Chris@16
|
168 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads,
|
Chris@16
|
169 BOOST_FUNCTIONAL_function_type, ~)
|
Chris@16
|
170 >(BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_arg, ~));
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 } // namespace
|
Chris@16
|
174
|
Chris@16
|
175 // For type-of emulation: Register overloaded function type (for _AUTO, etc).
|
Chris@16
|
176 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::overloaded_function,
|
Chris@16
|
177 BOOST_FUNCTIONAL_overloads)
|
Chris@16
|
178
|
Chris@16
|
179 # undef BOOST_FUNCTIONAL_overloads
|
Chris@16
|
180 # undef BOOST_FUNCTIONAL_is_tspec
|
Chris@16
|
181 #endif // iteration
|
Chris@16
|
182
|
Chris@16
|
183 // DOCUMENTATION //
|
Chris@16
|
184
|
Chris@16
|
185 #else // DOXYGEN
|
Chris@16
|
186
|
Chris@16
|
187 /** @file
|
Chris@16
|
188 @brief Overload distinct function pointers, function references, and
|
Chris@16
|
189 monomorphic function objects into a single function object.
|
Chris@16
|
190 */
|
Chris@16
|
191
|
Chris@16
|
192 namespace boost {
|
Chris@16
|
193
|
Chris@16
|
194 /**
|
Chris@16
|
195 @brief Function object to overload functions with distinct signatures.
|
Chris@16
|
196
|
Chris@16
|
197 This function object aggregates together calls to functions of all the
|
Chris@16
|
198 specified function types <c>F1</c>, <c>F2</c>, etc which must have distinct
|
Chris@16
|
199 function signatures from one another.
|
Chris@16
|
200
|
Chris@16
|
201 @Params
|
Chris@16
|
202 @Param{F<em>i</em>,
|
Chris@16
|
203 Each function type must be specified using the following syntax (which is
|
Chris@16
|
204 Boost.Function's preferred syntax):
|
Chris@16
|
205 @code
|
Chris@16
|
206 result_type (argument1_type\, argumgnet2_type\, ...)
|
Chris@16
|
207 @endcode
|
Chris@16
|
208 }
|
Chris@16
|
209 @EndParams
|
Chris@16
|
210
|
Chris@16
|
211 In some cases, the @RefFunc{make_overloaded_function} function template can be
|
Chris@16
|
212 useful to construct an overloaded function object without explicitly
|
Chris@16
|
213 specifying the function types.
|
Chris@16
|
214
|
Chris@16
|
215 At least two distinct function types must be specified (because there is
|
Chris@16
|
216 nothing to overload between one or zero functions).
|
Chris@16
|
217 The maximum number of functions to overload is given by the
|
Chris@16
|
218 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
|
Chris@16
|
219 configuration macro.
|
Chris@16
|
220 The maximum number of function parameters for each of the specified function
|
Chris@16
|
221 types is given by the
|
Chris@16
|
222 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}
|
Chris@16
|
223 configuration macro.
|
Chris@16
|
224
|
Chris@16
|
225 @See @RefSect{tutorial, Tutorial} section, @RefFunc{make_overloaded_function},
|
Chris@16
|
226 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX},
|
Chris@16
|
227 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX},
|
Chris@16
|
228 Boost.Function.
|
Chris@16
|
229 */
|
Chris@16
|
230 template<typename F1, typename F2, ...>
|
Chris@16
|
231 class overloaded_function {
|
Chris@16
|
232 public:
|
Chris@16
|
233 /**
|
Chris@16
|
234 @brief Construct the overloaded function object.
|
Chris@16
|
235
|
Chris@16
|
236 Any function pointer, function reference, and monomorphic function object
|
Chris@16
|
237 that can be converted to a <c>boost::function</c> function object can be
|
Chris@16
|
238 specified as parameter.
|
Chris@16
|
239
|
Chris@16
|
240 @Note Unfortunately, it is not possible to support polymorphic function
|
Chris@16
|
241 objects (as explained <a
|
Chris@16
|
242 href="http://lists.boost.org/Archives/boost/2012/03/191744.php">here</a>).
|
Chris@16
|
243 */
|
Chris@16
|
244 overloaded_function(const boost::function<F1>&,
|
Chris@16
|
245 const boost::function<F2>&, ...);
|
Chris@16
|
246
|
Chris@16
|
247 /**
|
Chris@16
|
248 @brief Call operator matching the signature of the function type specified
|
Chris@16
|
249 as 1st template parameter.
|
Chris@16
|
250
|
Chris@16
|
251 This will in turn invoke the call operator of the 1st function passed to
|
Chris@16
|
252 the constructor.
|
Chris@16
|
253 */
|
Chris@16
|
254 typename boost::function_traits<F1>::result_type operator()(
|
Chris@16
|
255 typename boost::function_traits<F1>::arg1_type,
|
Chris@16
|
256 typename boost::function_traits<F1>::arg2_type,
|
Chris@16
|
257 ...) const;
|
Chris@16
|
258
|
Chris@16
|
259 /**
|
Chris@16
|
260 @brief Call operator matching the signature of the function type specified
|
Chris@16
|
261 as 2nd template parameter.
|
Chris@16
|
262
|
Chris@16
|
263 This will in turn invoke the call operator of the 2nd function passed to
|
Chris@16
|
264 the constructor.
|
Chris@16
|
265
|
Chris@16
|
266 @Note Similar call operators are present for all specified function types
|
Chris@16
|
267 <c>F1</c>, <c>F2</c>, etc (even if not exhaustively listed by this
|
Chris@16
|
268 documentation).
|
Chris@16
|
269 */
|
Chris@16
|
270 typename boost::function_traits<F2>::result_type operator()(
|
Chris@16
|
271 typename boost::function_traits<F2>::arg1_type,
|
Chris@16
|
272 typename boost::function_traits<F2>::arg2_type,
|
Chris@16
|
273 ...) const;
|
Chris@16
|
274 };
|
Chris@16
|
275
|
Chris@16
|
276 /**
|
Chris@16
|
277 @brief Make an overloaded function object without explicitly specifying the
|
Chris@16
|
278 function types.
|
Chris@16
|
279
|
Chris@16
|
280 This function template creates and returns an @RefClass{overloaded_function}
|
Chris@16
|
281 object that overloads all the specified functions <c>f1</c>, <c>f2</c>, etc.
|
Chris@16
|
282
|
Chris@16
|
283 The function types are internally determined from the template parameter types
|
Chris@16
|
284 so they do not need to be explicitly specified.
|
Chris@16
|
285 Therefore, this function template usually has a more concise syntax when
|
Chris@16
|
286 compared with @RefClass{overloaded_function}.
|
Chris@16
|
287 This is especially useful when the explicit type of the returned
|
Chris@16
|
288 @RefClass{overloaded_function} object does not need to be known (e.g., when
|
Chris@16
|
289 used with Boost.Typeof's <c>BOOST_AUTO</c>, C++11 <c>auto</c>, or when the
|
Chris@16
|
290 overloaded function object is handled using a function template parameter, see
|
Chris@16
|
291 the @RefSect{tutorial, Tutorial} section).
|
Chris@16
|
292
|
Chris@16
|
293 The maximum number of functions to overload is given by the
|
Chris@16
|
294 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
|
Chris@16
|
295 configuration macro.
|
Chris@16
|
296
|
Chris@16
|
297 @Note In this documentation, <c>__function_type__</c> is a placeholder for a
|
Chris@16
|
298 symbol that is specific to the implementation of this library.
|
Chris@16
|
299
|
Chris@16
|
300 @See @RefSect{tutorial, Tutorial} section, @RefClass{overloaded_function},
|
Chris@16
|
301 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}.
|
Chris@16
|
302 */
|
Chris@16
|
303 template<typename F1, typename F2, ...>
|
Chris@16
|
304 overloaded_function<
|
Chris@16
|
305 __function_type__<F1>, __function_type__<F2>, ...
|
Chris@16
|
306 > make_overloaded_function(F1 f1, F2 f2, ...);
|
Chris@16
|
307
|
Chris@16
|
308 } // namespace
|
Chris@16
|
309
|
Chris@16
|
310 #endif // DOXYGEN
|
Chris@16
|
311
|