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