invoke.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*=============================================================================
  2. Copyright (c) 2005-2006 Joao Abecasis
  3. Copyright (c) 2006-2007 Tobias Schwinger
  4. Use modification and distribution are subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt).
  7. ==============================================================================*/
  8. #if !defined(BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED)
  9. #if !defined(BOOST_PP_IS_ITERATING)
  10. #include <boost/preprocessor/cat.hpp>
  11. #include <boost/preprocessor/iteration/iterate.hpp>
  12. #include <boost/preprocessor/arithmetic/dec.hpp>
  13. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  14. #include <boost/preprocessor/repetition/enum.hpp>
  15. #include <boost/preprocessor/repetition/enum_shifted.hpp>
  16. #include <boost/preprocessor/repetition/enum_params.hpp>
  17. #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
  18. #include <boost/mpl/if.hpp>
  19. #include <boost/mpl/eval_if.hpp>
  20. #include <boost/mpl/or.hpp>
  21. #include <boost/mpl/front.hpp>
  22. #include <boost/mpl/identity.hpp>
  23. #include <boost/type_traits/add_const.hpp>
  24. #include <boost/type_traits/remove_cv.hpp>
  25. #include <boost/type_traits/add_reference.hpp>
  26. #include <boost/type_traits/remove_reference.hpp>
  27. #include <boost/type_traits/is_convertible.hpp>
  28. #include <boost/function_types/is_function.hpp>
  29. #include <boost/function_types/is_callable_builtin.hpp>
  30. #include <boost/function_types/is_member_pointer.hpp>
  31. #include <boost/function_types/is_member_function_pointer.hpp>
  32. #include <boost/function_types/result_type.hpp>
  33. #include <boost/function_types/parameter_types.hpp>
  34. #include <boost/utility/result_of.hpp>
  35. #include <boost/core/enable_if.hpp>
  36. #include <boost/fusion/support/category_of.hpp>
  37. #include <boost/fusion/sequence/intrinsic/at.hpp>
  38. #include <boost/fusion/sequence/intrinsic/size.hpp>
  39. #include <boost/fusion/sequence/intrinsic/front.hpp>
  40. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  41. #include <boost/fusion/iterator/next.hpp>
  42. #include <boost/fusion/iterator/deref.hpp>
  43. #include <boost/fusion/functional/invocation/limits.hpp>
  44. #include <boost/fusion/functional/invocation/detail/that_ptr.hpp>
  45. namespace boost { namespace fusion
  46. {
  47. namespace detail
  48. {
  49. namespace ft = function_types;
  50. template<
  51. typename Function, class Sequence,
  52. int N = result_of::size<Sequence>::value,
  53. bool CBI = ft::is_callable_builtin<Function>::value,
  54. bool RandomAccess = traits::is_random_access<Sequence>::value,
  55. typename Enable = void
  56. >
  57. struct invoke_impl;
  58. template <class Sequence, int N>
  59. struct invoke_param_types;
  60. template <typename T, class Sequence>
  61. struct invoke_data_member;
  62. template <typename Function, class Sequence, int N, bool RandomAccess>
  63. struct invoke_fn_ptr;
  64. template <typename Function, class Sequence, int N, bool RandomAccess>
  65. struct invoke_mem_fn;
  66. #define BOOST_PP_FILENAME_1 <boost/fusion/functional/invocation/invoke.hpp>
  67. #define BOOST_PP_ITERATION_LIMITS (0, BOOST_FUSION_INVOKE_MAX_ARITY)
  68. #include BOOST_PP_ITERATE()
  69. template <typename F, class Sequence, int N, bool RandomAccess>
  70. struct invoke_nonmember_builtin
  71. // use same implementation as for function objects but...
  72. : invoke_fn_ptr< // ...work around boost::result_of bugs
  73. typename mpl::eval_if< ft::is_function<F>,
  74. boost::add_reference<F>, boost::remove_cv<F> >::type,
  75. Sequence, N, RandomAccess >
  76. { };
  77. template <typename Function, class Sequence, int N, bool RandomAccess, typename Enable>
  78. struct invoke_impl<Function,Sequence,N,true,RandomAccess,Enable>
  79. : mpl::if_< ft::is_member_function_pointer<Function>,
  80. invoke_mem_fn<Function,Sequence,N,RandomAccess>,
  81. invoke_nonmember_builtin<Function,Sequence,N,RandomAccess>
  82. >::type
  83. { };
  84. template <typename Function, class Sequence, bool RandomAccess, typename Enable>
  85. struct invoke_impl<Function,Sequence,1,true,RandomAccess,Enable>
  86. : mpl::eval_if< ft::is_member_pointer<Function>,
  87. mpl::if_< ft::is_member_function_pointer<Function>,
  88. invoke_mem_fn<Function,Sequence,1,RandomAccess>,
  89. invoke_data_member<Function, Sequence> >,
  90. mpl::identity< invoke_nonmember_builtin<
  91. Function,Sequence,1,RandomAccess> >
  92. >::type
  93. { };
  94. template <typename T, class C, class Sequence>
  95. struct invoke_data_member< T C::*, Sequence >
  96. {
  97. private:
  98. typedef typename result_of::front<Sequence>::type that;
  99. typedef mpl::or_< boost::is_convertible<that,C*>,
  100. boost::is_convertible<that,C&>,
  101. non_const_pointee<that> > non_const_cond;
  102. typedef typename mpl::eval_if< non_const_cond,
  103. mpl::identity<C>, add_const<C> >::type qualified_class;
  104. typedef typename mpl::eval_if< non_const_cond,
  105. mpl::identity<T>, add_const<T> >::type qualified_type;
  106. public:
  107. typedef typename boost::add_reference<qualified_type>::type
  108. result_type;
  109. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  110. static inline result_type call(T C::* f, Sequence & s)
  111. {
  112. typename result_of::front<Sequence>::type c = fusion::front(s);
  113. return that_ptr<qualified_class>::get(c)->*f;
  114. }
  115. };
  116. }
  117. namespace result_of
  118. {
  119. template <typename Function, class Sequence, typename = void>
  120. struct invoke;
  121. template <typename Function, class Sequence>
  122. struct invoke<Function, Sequence,
  123. typename enable_if_has_type<
  124. typename detail::invoke_impl<
  125. typename boost::remove_reference<Function>::type, Sequence
  126. >::result_type
  127. >::type>
  128. {
  129. typedef typename detail::invoke_impl<
  130. typename boost::remove_reference<Function>::type, Sequence
  131. >::result_type type;
  132. };
  133. }
  134. template <typename Function, class Sequence>
  135. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  136. inline typename result_of::invoke<Function,Sequence>::type
  137. invoke(Function f, Sequence & s)
  138. {
  139. return detail::invoke_impl<
  140. typename boost::remove_reference<Function>::type,Sequence
  141. >::call(f,s);
  142. }
  143. template <typename Function, class Sequence>
  144. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  145. inline typename result_of::invoke<Function,Sequence const>::type
  146. invoke(Function f, Sequence const & s)
  147. {
  148. return detail::invoke_impl<
  149. typename boost::remove_reference<Function>::type,Sequence const
  150. >::call(f,s);
  151. }
  152. }}
  153. #define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED
  154. #else // defined(BOOST_PP_IS_ITERATING)
  155. ///////////////////////////////////////////////////////////////////////////////
  156. //
  157. // Preprocessor vertical repetition code
  158. //
  159. ///////////////////////////////////////////////////////////////////////////////
  160. #define N BOOST_PP_ITERATION()
  161. #define M(z,j,data) typename result_of::at_c<Sequence,j>::type
  162. template <typename Function, class Sequence>
  163. struct invoke_impl<Function,Sequence,N,false,true,
  164. typename enable_if_has_type<
  165. typename boost::result_of<Function(BOOST_PP_ENUM(N,M,~)) >::type
  166. >::type>
  167. {
  168. public:
  169. typedef typename boost::result_of<
  170. Function(BOOST_PP_ENUM(N,M,~)) >::type result_type;
  171. #undef M
  172. #if N > 0
  173. template <typename F>
  174. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  175. static inline result_type
  176. call(F & f, Sequence & s)
  177. {
  178. #define M(z,j,data) fusion::at_c<j>(s)
  179. return f( BOOST_PP_ENUM(N,M,~) );
  180. }
  181. #else
  182. template <typename F>
  183. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  184. static inline result_type
  185. call(F & f, Sequence & /*s*/)
  186. {
  187. return f();
  188. }
  189. #endif
  190. };
  191. template <typename Function, class Sequence>
  192. struct invoke_fn_ptr<Function,Sequence,N,true>
  193. {
  194. public:
  195. typedef typename ft::result_type<Function>::type result_type;
  196. #if N > 0
  197. template <typename F>
  198. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  199. static inline result_type
  200. call(F & f, Sequence & s)
  201. {
  202. #define M(z,j,data) fusion::at_c<j>(s)
  203. return f( BOOST_PP_ENUM(N,M,~) );
  204. }
  205. #else
  206. template <typename F>
  207. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  208. static inline result_type
  209. call(F & f, Sequence & /*s*/)
  210. {
  211. return f();
  212. }
  213. #endif
  214. };
  215. #if N > 0
  216. template <typename Function, class Sequence>
  217. struct invoke_mem_fn<Function,Sequence,N,true>
  218. {
  219. public:
  220. typedef typename ft::result_type<Function>::type result_type;
  221. template <typename F>
  222. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  223. static inline result_type
  224. call(F & f, Sequence & s)
  225. {
  226. return (that_ptr<typename mpl::front<
  227. ft::parameter_types<Function> >::type
  228. >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~));
  229. }
  230. };
  231. #endif
  232. #undef M
  233. #define M(z,j,data) \
  234. typename seq::I##j i##j = \
  235. fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j)));
  236. template <typename Function, class Sequence>
  237. struct invoke_impl<Function,Sequence,N,false,false,
  238. typename enable_if_has_type<
  239. #define L(z,j,data) typename invoke_param_types<Sequence,N>::BOOST_PP_CAT(T, j)
  240. typename boost::result_of<Function(BOOST_PP_ENUM(N,L,~))>::type
  241. >::type>
  242. #undef L
  243. {
  244. private:
  245. typedef invoke_param_types<Sequence,N> seq;
  246. public:
  247. typedef typename boost::result_of<
  248. Function(BOOST_PP_ENUM_PARAMS(N,typename seq::T))
  249. >::type result_type;
  250. #if N > 0
  251. template <typename F>
  252. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  253. static inline result_type
  254. call(F & f, Sequence & s)
  255. {
  256. typename seq::I0 i0 = fusion::begin(s);
  257. BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
  258. return f( BOOST_PP_ENUM_PARAMS(N,*i) );
  259. }
  260. #else
  261. template <typename F>
  262. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  263. static inline result_type
  264. call(F & f, Sequence & /*s*/)
  265. {
  266. return f();
  267. }
  268. #endif
  269. };
  270. template <typename Function, class Sequence>
  271. struct invoke_fn_ptr<Function,Sequence,N,false>
  272. {
  273. private:
  274. typedef invoke_param_types<Sequence,N> seq;
  275. public:
  276. typedef typename ft::result_type<Function>::type result_type;
  277. #if N > 0
  278. template <typename F>
  279. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  280. static inline result_type
  281. call(F & f, Sequence & s)
  282. {
  283. typename seq::I0 i0 = fusion::begin(s);
  284. BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
  285. return f( BOOST_PP_ENUM_PARAMS(N,*i) );
  286. }
  287. #else
  288. template <typename F>
  289. BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  290. static inline result_type
  291. call(F & f, Sequence & /*s*/)
  292. {
  293. return f();
  294. }
  295. #endif
  296. };
  297. #if N > 0
  298. template <typename Function, class Sequence>
  299. struct invoke_mem_fn<Function,Sequence,N,false>
  300. {
  301. private:
  302. typedef invoke_param_types<Sequence,N> seq;
  303. public:
  304. typedef typename ft::result_type<Function>::type result_type;
  305. template <typename F>
  306. BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
  307. static inline result_type
  308. call(F & f, Sequence & s)
  309. {
  310. typename seq::I0 i0 = fusion::begin(s);
  311. BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
  312. return (that_ptr< typename mpl::front<
  313. ft::parameter_types<Function> >::type
  314. >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i));
  315. }
  316. };
  317. #endif
  318. #undef M
  319. template <class Sequence> struct invoke_param_types<Sequence,N>
  320. {
  321. #if N > 0
  322. typedef typename result_of::begin<Sequence>::type I0;
  323. typedef typename result_of::deref<I0>::type T0;
  324. #define M(z,i,data) \
  325. typedef typename result_of::next< \
  326. BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i; \
  327. typedef typename result_of::deref<I##i>::type T##i;
  328. BOOST_PP_REPEAT_FROM_TO(1,N,M,~)
  329. #undef M
  330. #endif
  331. };
  332. #undef N
  333. #endif // defined(BOOST_PP_IS_ITERATING)
  334. #endif