Chris@16: /*============================================================================= Chris@16: Copyright (c) 2005-2006 Joao Abecasis Chris@16: Copyright (c) 2006-2007 Tobias Schwinger Chris@16: Chris@16: Use modification and distribution are subject to the Boost Software Chris@16: License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: ==============================================================================*/ Chris@16: Chris@16: #if !defined(BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED) Chris@16: #if !defined(BOOST_PP_IS_ITERATING) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace fusion Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: namespace ft = function_types; Chris@16: Chris@16: template< Chris@16: typename Function, class Sequence, Chris@16: int N = result_of::size::value, Chris@16: bool CBI = ft::is_callable_builtin::value, Chris@101: bool RandomAccess = traits::is_random_access::value, Chris@101: typename Enable = void Chris@16: > Chris@16: struct invoke_impl; Chris@16: Chris@16: template Chris@16: struct invoke_param_types; Chris@16: Chris@16: template Chris@16: struct invoke_data_member; Chris@16: Chris@16: template Chris@16: struct invoke_fn_ptr; Chris@16: Chris@16: template Chris@16: struct invoke_mem_fn; Chris@16: Chris@16: #define BOOST_PP_FILENAME_1 Chris@16: #define BOOST_PP_ITERATION_LIMITS (0, BOOST_FUSION_INVOKE_MAX_ARITY) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: template Chris@16: struct invoke_nonmember_builtin Chris@16: // use same implementation as for function objects but... Chris@16: : invoke_fn_ptr< // ...work around boost::result_of bugs Chris@16: typename mpl::eval_if< ft::is_function, Chris@16: boost::add_reference, boost::remove_cv >::type, Chris@16: Sequence, N, RandomAccess > Chris@16: { }; Chris@16: Chris@101: template Chris@101: struct invoke_impl Chris@16: : mpl::if_< ft::is_member_function_pointer, Chris@16: invoke_mem_fn, Chris@16: invoke_nonmember_builtin Chris@16: >::type Chris@16: { }; Chris@16: Chris@101: template Chris@101: struct invoke_impl Chris@16: : mpl::eval_if< ft::is_member_pointer, Chris@16: mpl::if_< ft::is_member_function_pointer, Chris@16: invoke_mem_fn, Chris@16: invoke_data_member >, Chris@16: mpl::identity< invoke_nonmember_builtin< Chris@16: Function,Sequence,1,RandomAccess> > Chris@16: >::type Chris@16: { }; Chris@16: Chris@16: template Chris@16: struct invoke_data_member< T C::*, Sequence > Chris@16: { Chris@16: private: Chris@16: Chris@16: typedef typename result_of::front::type that; Chris@16: Chris@16: typedef mpl::or_< boost::is_convertible, Chris@16: boost::is_convertible, Chris@16: non_const_pointee > non_const_cond; Chris@16: Chris@16: typedef typename mpl::eval_if< non_const_cond, Chris@16: mpl::identity, add_const >::type qualified_class; Chris@16: Chris@16: typedef typename mpl::eval_if< non_const_cond, Chris@16: mpl::identity, add_const >::type qualified_type; Chris@16: Chris@16: public: Chris@16: Chris@16: typedef typename boost::add_reference::type Chris@16: result_type; Chris@16: Chris@101: BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type call(T C::* f, Sequence & s) Chris@16: { Chris@16: typename result_of::front::type c = fusion::front(s); Chris@16: return that_ptr::get(c)->*f; Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: namespace result_of Chris@16: { Chris@101: template Chris@101: struct invoke; Chris@101: Chris@101: template Chris@101: struct invoke::type, Sequence Chris@101: >::result_type Chris@101: >::type> Chris@16: { Chris@16: typedef typename detail::invoke_impl< Chris@16: typename boost::remove_reference::type, Sequence Chris@101: >::result_type type; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: inline typename result_of::invoke::type Chris@16: invoke(Function f, Sequence & s) Chris@16: { Chris@16: return detail::invoke_impl< Chris@16: typename boost::remove_reference::type,Sequence Chris@16: >::call(f,s); Chris@16: } Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: inline typename result_of::invoke::type Chris@16: invoke(Function f, Sequence const & s) Chris@16: { Chris@16: return detail::invoke_impl< Chris@16: typename boost::remove_reference::type,Sequence const Chris@16: >::call(f,s); Chris@16: } Chris@16: Chris@16: }} Chris@16: Chris@16: #define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED Chris@16: #else // defined(BOOST_PP_IS_ITERATING) Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Preprocessor vertical repetition code Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: #define N BOOST_PP_ITERATION() Chris@16: Chris@101: #define M(z,j,data) typename result_of::at_c::type Chris@101: Chris@16: template Chris@101: struct invoke_impl::type Chris@101: >::type> Chris@16: { Chris@16: public: Chris@16: Chris@16: typedef typename boost::result_of< Chris@16: Function(BOOST_PP_ENUM(N,M,~)) >::type result_type; Chris@16: #undef M Chris@16: Chris@16: #if N > 0 Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: #define M(z,j,data) fusion::at_c(s) Chris@16: return f( BOOST_PP_ENUM(N,M,~) ); Chris@16: } Chris@16: Chris@16: #else Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & /*s*/) Chris@16: { Chris@16: return f(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: struct invoke_fn_ptr Chris@16: { Chris@16: public: Chris@16: Chris@16: typedef typename ft::result_type::type result_type; Chris@16: Chris@16: #if N > 0 Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: #define M(z,j,data) fusion::at_c(s) Chris@16: return f( BOOST_PP_ENUM(N,M,~) ); Chris@16: } Chris@16: Chris@16: #else Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & /*s*/) Chris@16: { Chris@16: return f(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: Chris@16: #if N > 0 Chris@16: template Chris@16: struct invoke_mem_fn Chris@16: { Chris@16: public: Chris@16: Chris@16: typedef typename ft::result_type::type result_type; Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: return (that_ptr >::type Chris@16: >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~)); Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: Chris@16: #undef M Chris@16: Chris@16: #define M(z,j,data) \ Chris@16: typename seq::I##j i##j = \ Chris@16: fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j))); Chris@16: Chris@16: template Chris@101: struct invoke_impl::BOOST_PP_CAT(T, j) Chris@101: typename boost::result_of::type Chris@101: >::type> Chris@101: #undef L Chris@16: { Chris@16: private: Chris@16: typedef invoke_param_types seq; Chris@16: public: Chris@16: Chris@16: typedef typename boost::result_of< Chris@16: Function(BOOST_PP_ENUM_PARAMS(N,typename seq::T)) Chris@16: >::type result_type; Chris@16: Chris@16: #if N > 0 Chris@16: Chris@16: template Chris@101: BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: typename seq::I0 i0 = fusion::begin(s); Chris@16: BOOST_PP_REPEAT_FROM_TO(1,N,M,~) Chris@16: return f( BOOST_PP_ENUM_PARAMS(N,*i) ); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & /*s*/) Chris@16: { Chris@16: return f(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: template Chris@16: struct invoke_fn_ptr Chris@16: { Chris@16: private: Chris@16: typedef invoke_param_types seq; Chris@16: public: Chris@16: Chris@16: typedef typename ft::result_type::type result_type; Chris@16: Chris@16: #if N > 0 Chris@16: Chris@16: template Chris@101: BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: typename seq::I0 i0 = fusion::begin(s); Chris@16: BOOST_PP_REPEAT_FROM_TO(1,N,M,~) Chris@16: return f( BOOST_PP_ENUM_PARAMS(N,*i) ); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: template Chris@101: BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & /*s*/) Chris@16: { Chris@16: return f(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: }; Chris@16: Chris@16: #if N > 0 Chris@16: template Chris@16: struct invoke_mem_fn Chris@16: { Chris@16: private: Chris@16: typedef invoke_param_types seq; Chris@16: public: Chris@16: Chris@16: typedef typename ft::result_type::type result_type; Chris@16: Chris@16: template Chris@101: BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED Chris@16: static inline result_type Chris@16: call(F & f, Sequence & s) Chris@16: { Chris@16: typename seq::I0 i0 = fusion::begin(s); Chris@16: BOOST_PP_REPEAT_FROM_TO(1,N,M,~) Chris@16: Chris@16: return (that_ptr< typename mpl::front< Chris@16: ft::parameter_types >::type Chris@16: >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i)); Chris@16: } Chris@16: }; Chris@16: #endif Chris@16: Chris@16: #undef M Chris@16: Chris@16: template struct invoke_param_types Chris@16: { Chris@16: #if N > 0 Chris@16: typedef typename result_of::begin::type I0; Chris@16: typedef typename result_of::deref::type T0; Chris@16: Chris@16: #define M(z,i,data) \ Chris@16: typedef typename result_of::next< \ Chris@16: BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i; \ Chris@16: typedef typename result_of::deref::type T##i; Chris@16: Chris@16: BOOST_PP_REPEAT_FROM_TO(1,N,M,~) Chris@16: #undef M Chris@16: #endif Chris@16: }; Chris@16: Chris@16: Chris@16: #undef N Chris@16: #endif // defined(BOOST_PP_IS_ITERATING) Chris@16: #endif Chris@16: