overloaded_function.hpp 11 KB

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