1 
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
7 
8 #ifndef DOXYGEN // Doxygen documentation only.
9 
10 #if !BOOST_PP_IS_ITERATING
11 #   ifndef BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
12 #       define BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_HPP_
13 
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>
32 
33 #define BOOST_FUNCTIONAL_f_type(z, n, unused) \
34     BOOST_PP_CAT(F, n)
35 
36 #define BOOST_FUNCTIONAL_f_arg(z, n, unused) \
37     BOOST_PP_CAT(f, n)
38 
39 #define BOOST_FUNCTIONAL_f_tparam(z, n, unused) \
40     typename BOOST_FUNCTIONAL_f_type(z, n, ~) \
41 
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)), \
47         = void \
48     )
49 
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, ~)
53 
54 #define BOOST_FUNCTIONAL_g_type(z, n, unused) \
55     BOOST_PP_CAT(G, n)
56 
57 #define BOOST_FUNCTIONAL_g_arg(z, n, unused) \
58     BOOST_PP_CAT(g, n)
59 
60 #define BOOST_FUNCTIONAL_g_tparam(z, n, unused) \
61     typename BOOST_FUNCTIONAL_g_type(z, n, ~)
62 
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, ~)
66 
67 #define BOOST_FUNCTIONAL_base(z, n, unused) \
68     ::boost::overloaded_function_detail::base< \
69         BOOST_FUNCTIONAL_f_type(z, n, ~) \
70     >
71 
72 #define BOOST_FUNCTIONAL_inherit(z, n, unused) \
73     public BOOST_FUNCTIONAL_base(z, n, ~)
74 
75 #define BOOST_FUNCTIONAL_base_init(z, n, unused) \
76     BOOST_FUNCTIONAL_base(z, n, ~)(BOOST_FUNCTIONAL_g_arg(z, n, ~))
77 
78 #define BOOST_FUNCTIONAL_using_operator_call(z, n, unused) \
79     using BOOST_FUNCTIONAL_base(z, n, ~)::operator();
80 
81 #define BOOST_FUNCTIONAL_function_type(z, n, unused) \
82     typename ::boost::overloaded_function_detail::function_type< \
83         BOOST_FUNCTIONAL_f_type(z, n, ~) \
84     >::type
85 
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.
92 
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
107 
108 #   endif // #include guard
109 
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)
121 
122 // For type-of emulation: This must be included at this pp iteration level.
123 #   include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
124 
125 namespace boost {
126 
127 template<
128     BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt,
129             BOOST_FUNCTIONAL_is_tspec)
130 >
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,
135         BOOST_PP_ENUM
136     ,
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, ~)
143 {
144 public:
145     template<
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, ~)
153     {}
154 
155     BOOST_PP_REPEAT(BOOST_FUNCTIONAL_overloads,
156             BOOST_FUNCTIONAL_using_operator_call, ~)
157 };
158 
159 template<
160     BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~)
161 >
162 overloaded_function<
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, ~)
166 ) {
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, ~));
171 }
172 
173 } // namespace
174 
175 // For type-of emulation: Register overloaded function type (for _AUTO, etc).
176 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::overloaded_function,
177     BOOST_FUNCTIONAL_overloads)
178 
179 #   undef BOOST_FUNCTIONAL_overloads
180 #   undef BOOST_FUNCTIONAL_is_tspec
181 #endif // iteration
182 
183 // DOCUMENTATION //
184 
185 #else // DOXYGEN
186 
187 /** @file
188 @brief Overload distinct function pointers, function references, and
189 monomorphic function objects into a single function object.
190 */
191 
192 namespace boost {
193 
194 /**
195 @brief Function object to overload functions with distinct signatures.
196 
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.
200 
201 @Params
202 @Param{F<em>i</em>,
203 Each function type must be specified using the following syntax (which is
204 Boost.Function's preferred syntax):
205 @code
206     result_type (argument1_type\, argumgnet2_type\, ...)
207 @endcode
208 }
209 @EndParams
210 
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.
214 
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}
219 configuration macro.
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}
223 configuration macro.
224 
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},
228 Boost.Function.
229 */
230 template<typename F1, typename F2, ...>
231 class overloaded_function {
232 public:
233     /**
234     @brief Construct the overloaded function object.
235 
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.
239 
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>).
243     */
244     overloaded_function(const boost::function<F1>&,
245             const boost::function<F2>&, ...);
246 
247     /**
248     @brief Call operator matching the signature of the function type specified
249     as 1st template parameter.
250 
251     This will in turn invoke the call operator of the 1st function passed to
252     the constructor.
253     */
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,
257             ...) const;
258 
259     /**
260     @brief Call operator matching the signature of the function type specified
261     as 2nd template parameter.
262 
263     This will in turn invoke the call operator of the 2nd function passed to
264     the constructor.
265 
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
268     documentation).
269     */
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,
273             ...) const;
274 };
275 
276 /**
277 @brief Make an overloaded function object without explicitly specifying the
278 function types.
279 
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.
282 
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).
292 
293 The maximum number of functions to overload is given by the
294 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
295 configuration macro.
296 
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.
299 
300 @See @RefSect{tutorial, Tutorial} section, @RefClass{overloaded_function},
301 @RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}.
302 */
303 template<typename F1, typename F2, ...>
304 overloaded_function<
305     __function_type__<F1>, __function_type__<F2>, ...
306 > make_overloaded_function(F1 f1, F2 f2, ...);
307 
308 } // namespace
309 
310 #endif // DOXYGEN
311 
312