callable.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Boost.TypeErasure library
  2. //
  3. // Copyright 2011 Steven Watanabe
  4. //
  5. // Distributed under the Boost Software License Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // $Id$
  10. #if !defined(BOOST_PP_IS_ITERATING)
  11. #ifndef BOOST_TYPE_ERASURE_CALLABLE_HPP_INCLUDED
  12. #define BOOST_TYPE_ERASURE_CALLABLE_HPP_INCLUDED
  13. #include <boost/detail/workaround.hpp>
  14. #include <boost/utility/declval.hpp>
  15. #include <boost/mpl/vector.hpp>
  16. #include <boost/mpl/push_back.hpp>
  17. #include <boost/preprocessor/cat.hpp>
  18. #include <boost/preprocessor/dec.hpp>
  19. #include <boost/preprocessor/iteration/iterate.hpp>
  20. #include <boost/preprocessor/repetition/enum.hpp>
  21. #include <boost/preprocessor/repetition/enum_params.hpp>
  22. #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  23. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  24. #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
  25. #include <boost/type_erasure/config.hpp>
  26. #include <boost/type_erasure/call.hpp>
  27. #include <boost/type_erasure/concept_interface.hpp>
  28. #include <boost/type_erasure/rebind_any.hpp>
  29. #include <boost/type_erasure/param.hpp>
  30. namespace boost {
  31. namespace type_erasure {
  32. template<class Sig, class F = _self>
  33. struct callable;
  34. namespace detail {
  35. template<class Sig>
  36. struct result_of_callable;
  37. }
  38. #if defined(BOOST_TYPE_ERASURE_DOXYGEN)
  39. /**
  40. * The @ref callable concept allows an @ref any to hold function objects.
  41. * @c Sig is interpreted in the same way as for Boost.Function, except
  42. * that the arguments and return type are allowed to be placeholders.
  43. * @c F must be a @ref placeholder.
  44. *
  45. * Multiple instances of @ref callable can be used
  46. * simultaneously. Overload resolution works normally.
  47. * Note that unlike Boost.Function, @ref callable
  48. * does not provide result_type. It does, however,
  49. * support @c boost::result_of.
  50. */
  51. template<class Sig, class F = _self>
  52. struct callable
  53. {
  54. /**
  55. * @c R is the result type of @c Sig and @c T is the argument
  56. * types of @c Sig.
  57. */
  58. static R apply(F& f, T... arg);
  59. };
  60. #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  61. !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
  62. !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
  63. template<class R, class... T, class F>
  64. struct callable<R(T...), F>
  65. {
  66. static R apply(F& f, T... arg)
  67. {
  68. return f(std::forward<T>(arg)...);
  69. }
  70. };
  71. template<class... T, class F>
  72. struct callable<void(T...), F>
  73. {
  74. static void apply(F& f, T... arg)
  75. {
  76. f(std::forward<T>(arg)...);
  77. }
  78. };
  79. template<class R, class F, class Base, class Enable, class... T>
  80. struct concept_interface<callable<R(T...), F>, Base, F, Enable>
  81. : Base
  82. {
  83. template<class Sig>
  84. struct result :
  85. ::boost::type_erasure::detail::result_of_callable<Sig>
  86. {};
  87. typedef void _boost_type_erasure_is_callable;
  88. typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
  89. typedef char (&_boost_type_erasure_callable_size)[1];
  90. _boost_type_erasure_callable_size
  91. _boost_type_erasure_deduce_callable(
  92. typename ::boost::type_erasure::as_param<Base, T>::type...);
  93. typename ::boost::type_erasure::rebind_any<Base, R>::type
  94. operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg)
  95. {
  96. return ::boost::type_erasure::call(callable<R(T...), F>(), *this,
  97. ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
  98. }
  99. };
  100. template<class R, class F, class Base, class Enable, class... T>
  101. struct concept_interface<callable<R(T...), const F>, Base, F, Enable>
  102. : Base
  103. {
  104. template<class Sig>
  105. struct result :
  106. ::boost::type_erasure::detail::result_of_callable<Sig>
  107. {};
  108. typedef void _boost_type_erasure_is_callable;
  109. typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
  110. typedef char (&_boost_type_erasure_callable_size)[1];
  111. _boost_type_erasure_callable_size
  112. _boost_type_erasure_deduce_callable(
  113. typename ::boost::type_erasure::as_param<Base, T>::type...) const;
  114. typename ::boost::type_erasure::rebind_any<Base, R>::type operator()(
  115. typename ::boost::type_erasure::as_param<Base, T>::type... arg) const
  116. {
  117. return ::boost::type_erasure::call(callable<R(T...), const F>(), *this,
  118. ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
  119. }
  120. };
  121. template<class R, class F, class Base, class... T>
  122. struct concept_interface<
  123. callable<R(T...), F>,
  124. Base,
  125. F,
  126. typename Base::_boost_type_erasure_is_callable
  127. >
  128. : Base
  129. {
  130. typedef typename ::boost::mpl::push_back<
  131. typename Base::_boost_type_erasure_callable_results,
  132. R
  133. >::type _boost_type_erasure_callable_results;
  134. typedef char (&_boost_type_erasure_callable_size)[
  135. ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
  136. using Base::_boost_type_erasure_deduce_callable;
  137. _boost_type_erasure_callable_size
  138. _boost_type_erasure_deduce_callable(
  139. typename ::boost::type_erasure::as_param<Base, T>::type...);
  140. using Base::operator();
  141. typename ::boost::type_erasure::rebind_any<Base, R>::type
  142. operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg)
  143. {
  144. return ::boost::type_erasure::call(callable<R(T...), F>(), *this,
  145. ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
  146. }
  147. };
  148. template<class R, class F, class Base, class... T>
  149. struct concept_interface<
  150. callable<R(T...), const F>,
  151. Base,
  152. F,
  153. typename Base::_boost_type_erasure_is_callable
  154. >
  155. : Base
  156. {
  157. typedef typename ::boost::mpl::push_back<
  158. typename Base::_boost_type_erasure_callable_results,
  159. R
  160. >::type _boost_type_erasure_callable_results;
  161. typedef char (&_boost_type_erasure_callable_size)[
  162. ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
  163. using Base::_boost_type_erasure_deduce_callable;
  164. _boost_type_erasure_callable_size
  165. _boost_type_erasure_deduce_callable(
  166. typename ::boost::type_erasure::as_param<Base, T>::type...) const;
  167. using Base::operator();
  168. typename ::boost::type_erasure::rebind_any<Base, R>::type
  169. operator()(typename ::boost::type_erasure::as_param<Base, T>::type... arg) const
  170. {
  171. return ::boost::type_erasure::call(callable<R(T...), const F>(), *this,
  172. ::std::forward<typename ::boost::type_erasure::as_param<Base, T>::type>(arg)...);
  173. }
  174. };
  175. namespace detail {
  176. template<class This, class... T>
  177. struct result_of_callable<This(T...)>
  178. {
  179. typedef typename ::boost::mpl::at_c<
  180. typename This::_boost_type_erasure_callable_results,
  181. sizeof(::boost::declval<This>().
  182. _boost_type_erasure_deduce_callable(::boost::declval<T>()...)) - 1
  183. >::type type;
  184. };
  185. }
  186. #else
  187. /** INTERNAL ONLY */
  188. #define BOOST_PP_FILENAME_1 <boost/type_erasure/callable.hpp>
  189. /** INTERNAL ONLY */
  190. #define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_DEC(BOOST_TYPE_ERASURE_MAX_ARITY))
  191. #include BOOST_PP_ITERATE()
  192. #endif
  193. }
  194. }
  195. #endif
  196. #else
  197. #define N BOOST_PP_ITERATION()
  198. #define BOOST_TYPE_ERASURE_DECLVAL(z, n, data) ::boost::declval<BOOST_PP_CAT(T, n)>()
  199. #define BOOST_TYPE_ERASURE_REBIND(z, n, data)\
  200. typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)>::type BOOST_PP_CAT(arg, n)
  201. #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
  202. #define BOOST_TYPE_ERASURE_FORWARD(z, n, data) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n)
  203. #define BOOST_TYPE_ERASURE_FORWARD_REBIND(z, n, data) BOOST_PP_CAT(arg, n)
  204. #else
  205. #define BOOST_TYPE_ERASURE_FORWARD(z, n, data) ::std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n)>(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n))
  206. #define BOOST_TYPE_ERASURE_FORWARD_REBIND(z, n, data) ::std::forward<typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(T, n)>::type>(BOOST_PP_CAT(arg, n))
  207. #endif
  208. template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F>
  209. struct callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>
  210. {
  211. static R apply(F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, T, arg))
  212. {
  213. return f(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FORWARD, (T, arg)));
  214. }
  215. };
  216. template<BOOST_PP_ENUM_PARAMS(N, class T) BOOST_PP_COMMA_IF(N) class F>
  217. struct callable<void(BOOST_PP_ENUM_PARAMS(N, T)), F>
  218. {
  219. static void apply(F& f BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, T, arg))
  220. {
  221. f(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_FORWARD, (T, arg)));
  222. }
  223. };
  224. template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base, class Enable>
  225. struct concept_interface<
  226. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>,
  227. Base,
  228. F,
  229. Enable
  230. >
  231. : Base
  232. {
  233. template<class Sig>
  234. struct result :
  235. ::boost::type_erasure::detail::result_of_callable<Sig>
  236. {};
  237. typedef void _boost_type_erasure_is_callable;
  238. typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
  239. typedef char (&_boost_type_erasure_callable_size)[1];
  240. _boost_type_erasure_callable_size
  241. _boost_type_erasure_deduce_callable(
  242. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~));
  243. typename ::boost::type_erasure::rebind_any<Base, R>::type
  244. operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~))
  245. {
  246. return ::boost::type_erasure::call(
  247. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>(),
  248. *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
  249. }
  250. };
  251. template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base, class Enable>
  252. struct concept_interface<
  253. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>,
  254. Base,
  255. F,
  256. Enable
  257. >
  258. : Base
  259. {
  260. template<class Sig>
  261. struct result :
  262. ::boost::type_erasure::detail::result_of_callable<Sig>
  263. {};
  264. typedef void _boost_type_erasure_is_callable;
  265. typedef ::boost::mpl::vector<R> _boost_type_erasure_callable_results;
  266. typedef char (&_boost_type_erasure_callable_size)[1];
  267. _boost_type_erasure_callable_size
  268. _boost_type_erasure_deduce_callable(
  269. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const;
  270. typename ::boost::type_erasure::rebind_any<Base, R>::type
  271. operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const
  272. {
  273. return ::boost::type_erasure::call(
  274. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>(),
  275. *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
  276. }
  277. };
  278. template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base>
  279. struct concept_interface<
  280. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>,
  281. Base,
  282. F,
  283. typename Base::_boost_type_erasure_is_callable
  284. >
  285. : Base
  286. {
  287. typedef typename ::boost::mpl::push_back<
  288. typename Base::_boost_type_erasure_callable_results,
  289. R
  290. >::type _boost_type_erasure_callable_results;
  291. typedef char (&_boost_type_erasure_callable_size)[
  292. ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
  293. using Base::_boost_type_erasure_deduce_callable;
  294. _boost_type_erasure_callable_size
  295. _boost_type_erasure_deduce_callable(
  296. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~));
  297. using Base::operator();
  298. typename ::boost::type_erasure::rebind_any<Base, R>::type
  299. operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~))
  300. {
  301. return ::boost::type_erasure::call(
  302. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), F>(),
  303. *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
  304. }
  305. };
  306. template<class R BOOST_PP_ENUM_TRAILING_PARAMS(N, class T), class F, class Base>
  307. struct concept_interface<
  308. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>,
  309. Base,
  310. F,
  311. typename Base::_boost_type_erasure_is_callable
  312. >
  313. : Base
  314. {
  315. typedef typename ::boost::mpl::push_back<
  316. typename Base::_boost_type_erasure_callable_results,
  317. R
  318. >::type _boost_type_erasure_callable_results;
  319. typedef char (&_boost_type_erasure_callable_size)[
  320. ::boost::mpl::size<_boost_type_erasure_callable_results>::value];
  321. using Base::_boost_type_erasure_deduce_callable;
  322. _boost_type_erasure_callable_size
  323. _boost_type_erasure_deduce_callable(
  324. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const;
  325. using Base::operator();
  326. typename ::boost::type_erasure::rebind_any<Base, R>::type
  327. operator()(BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_REBIND, ~)) const
  328. {
  329. return ::boost::type_erasure::call(
  330. callable<R(BOOST_PP_ENUM_PARAMS(N, T)), const F>(),
  331. *this BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND, ~));
  332. }
  333. };
  334. namespace detail {
  335. template<class This BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
  336. struct result_of_callable<This(BOOST_PP_ENUM_PARAMS(N, T))>
  337. {
  338. typedef typename ::boost::mpl::at_c<
  339. typename This::_boost_type_erasure_callable_results,
  340. sizeof(::boost::declval<This>().
  341. _boost_type_erasure_deduce_callable(
  342. BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_DECLVAL, ~))) - 1
  343. >::type type;
  344. };
  345. }
  346. #undef BOOST_TYPE_ERASURE_DECLVAL
  347. #undef BOOST_TYPE_ERASURE_REBIND
  348. #undef N
  349. #endif