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