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