blob: d2a1369a489ff76bf5a5ad0518bee72102ee1f58 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001
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 <ndnboost/functional/overloaded_function/detail/base.hpp>
15# include <ndnboost/functional/overloaded_function/detail/function_type.hpp>
16# include <ndnboost/functional/overloaded_function/config.hpp>
17# include <ndnboost/typeof/typeof.hpp>
18# include <ndnboost/preprocessor/iteration/iterate.hpp>
19# include <ndnboost/preprocessor/repetition/enum.hpp>
20# include <ndnboost/preprocessor/repetition/repeat.hpp>
21# include <ndnboost/preprocessor/control/expr_iif.hpp>
22# include <ndnboost/preprocessor/control/expr_if.hpp>
23# include <ndnboost/preprocessor/comparison/greater.hpp>
24# include <ndnboost/preprocessor/comparison/less.hpp>
25# include <ndnboost/preprocessor/cat.hpp>
26# include <ndnboost/preprocessor/arithmetic/add.hpp>
27# include <ndnboost/preprocessor/arithmetic/sub.hpp>
28# include <ndnboost/preprocessor/tuple/eat.hpp>
29# include <ndnboost/preprocessor/logical/and.hpp>
30# include <ndnboost/preprocessor/logical/not.hpp>
31# include <ndnboost/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 ::ndnboost::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 ::ndnboost::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 "ndnboost/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
125namespace ndnboost {
126
127template<
128 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam_dflt,
129 BOOST_FUNCTIONAL_is_tspec)
130>
131class 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{
144public:
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
159template<
160 BOOST_PP_ENUM(BOOST_FUNCTIONAL_overloads, BOOST_FUNCTIONAL_f_tparam, ~)
161>
162overloaded_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).
176BOOST_TYPEOF_REGISTER_TEMPLATE(ndnboost::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
189monomorphic function objects into a single function object.
190*/
191
192namespace ndnboost {
193
194/**
195@brief Function object to overload functions with distinct signatures.
196
197This function object aggregates together calls to functions of all the
198specified function types <c>F1</c>, <c>F2</c>, etc which must have distinct
199function signatures from one another.
200
201@Params
202@Param{F<em>i</em>,
203Each function type must be specified using the following syntax (which is
204Boost.Function's preferred syntax):
205@code
206 result_type (argument1_type\, argumgnet2_type\, ...)
207@endcode
208}
209@EndParams
210
211In some cases, the @RefFunc{make_overloaded_function} function template can be
212useful to construct an overloaded function object without explicitly
213specifying the function types.
214
215At least two distinct function types must be specified (because there is
216nothing to overload between one or zero functions).
217The maximum number of functions to overload is given by the
218@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
219configuration macro.
220The maximum number of function parameters for each of the specified function
221types is given by the
222@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_ARITY_MAX}
223configuration 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},
228Boost.Function.
229*/
230template<typename F1, typename F2, ...>
231class overloaded_function {
232public:
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>ndnboost::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 ndnboost::function<F1>&,
245 const ndnboost::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 ndnboost::function_traits<F1>::result_type operator()(
255 typename ndnboost::function_traits<F1>::arg1_type,
256 typename ndnboost::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 ndnboost::function_traits<F2>::result_type operator()(
271 typename ndnboost::function_traits<F2>::arg1_type,
272 typename ndnboost::function_traits<F2>::arg2_type,
273 ...) const;
274};
275
276/**
277@brief Make an overloaded function object without explicitly specifying the
278function types.
279
280This function template creates and returns an @RefClass{overloaded_function}
281object that overloads all the specified functions <c>f1</c>, <c>f2</c>, etc.
282
283The function types are internally determined from the template parameter types
284so they do not need to be explicitly specified.
285Therefore, this function template usually has a more concise syntax when
286compared with @RefClass{overloaded_function}.
287This is especially useful when the explicit type of the returned
288@RefClass{overloaded_function} object does not need to be known (e.g., when
289used with Boost.Typeof's <c>BOOST_AUTO</c>, C++11 <c>auto</c>, or when the
290overloaded function object is handled using a function template parameter, see
291the @RefSect{tutorial, Tutorial} section).
292
293The maximum number of functions to overload is given by the
294@RefMacro{BOOST_FUNCTIONAL_OVERLOADED_FUNCTION_CONFIG_OVERLOAD_MAX}
295configuration macro.
296
297@Note In this documentation, <c>__function_type__</c> is a placeholder for a
298symbol 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*/
303template<typename F1, typename F2, ...>
304overloaded_function<
305 __function_type__<F1>, __function_type__<F2>, ...
306> make_overloaded_function(F1 f1, F2 f2, ...);
307
308} // namespace
309
310#endif // DOXYGEN
311