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_PROCEDURE_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/type_traits/remove_reference.hpp> 23 24 #include <boost/mpl/front.hpp> 25 26 #include <boost/function_types/is_callable_builtin.hpp> 27 #include <boost/function_types/is_member_function_pointer.hpp> 28 #include <boost/function_types/parameter_types.hpp> 29 30 #include <boost/fusion/support/category_of.hpp> 31 #include <boost/fusion/support/detail/enabler.hpp> 32 #include <boost/fusion/sequence/intrinsic/at.hpp> 33 #include <boost/fusion/sequence/intrinsic/size.hpp> 34 #include <boost/fusion/sequence/intrinsic/begin.hpp> 35 #include <boost/fusion/iterator/next.hpp> 36 #include <boost/fusion/iterator/deref.hpp> 37 #include <boost/fusion/functional/invocation/limits.hpp> 38 #include <boost/fusion/functional/invocation/detail/that_ptr.hpp> 39 40 namespace boost { namespace fusion 41 { 42 namespace detail 43 { 44 namespace ft = function_types; 45 46 template< 47 typename Function, class Sequence, 48 int N = result_of::size<Sequence>::value, 49 bool MFP = ft::is_member_function_pointer<Function>::value, 50 bool RandomAccess = traits::is_random_access<Sequence>::value 51 > 52 struct invoke_procedure_impl; 53 54 #define BOOST_PP_FILENAME_1 \ 55 <boost/fusion/functional/invocation/invoke_procedure.hpp> 56 #define BOOST_PP_ITERATION_LIMITS \ 57 (0, BOOST_FUSION_INVOKE_PROCEDURE_MAX_ARITY) 58 #include BOOST_PP_ITERATE() 59 60 } 61 62 namespace result_of 63 { 64 template <typename Function, class Sequence, class Enable = void> 65 struct invoke_procedure; 66 67 template <typename Function, class Sequence> 68 struct invoke_procedure<Function, Sequence, 69 typename detail::enabler< 70 typename detail::invoke_procedure_impl< 71 typename boost::remove_reference<Function>::type,Sequence 72 >::result_type 73 >::type> 74 { 75 typedef void type; 76 }; 77 } 78 79 template <typename Function, class Sequence> 80 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 81 inline typename result_of::invoke_procedure<Function, Sequence>::type invoke_procedure(Function f,Sequence & s)82 invoke_procedure(Function f, Sequence & s) 83 { 84 detail::invoke_procedure_impl< 85 typename boost::remove_reference<Function>::type,Sequence 86 >::call(f,s); 87 } 88 89 template <typename Function, class Sequence> 90 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 91 inline typename result_of::invoke_procedure<Function, Sequence const>::type invoke_procedure(Function f,Sequence const & s)92 invoke_procedure(Function f, Sequence const & s) 93 { 94 detail::invoke_procedure_impl< 95 typename boost::remove_reference<Function>::type,Sequence const 96 >::call(f,s); 97 } 98 99 }} 100 101 #define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_PROCEDURE_HPP_INCLUDED 102 #else // defined(BOOST_PP_IS_ITERATING) 103 /////////////////////////////////////////////////////////////////////////////// 104 // 105 // Preprocessor vertical repetition code 106 // 107 /////////////////////////////////////////////////////////////////////////////// 108 #define N BOOST_PP_ITERATION() 109 110 #define M(z,j,data) fusion::at_c<j>(s) 111 112 template <typename Function, class Sequence> 113 struct invoke_procedure_impl<Function,Sequence,N,false,true> 114 { 115 typedef void result_type; 116 117 #if N > 0 118 119 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl120 static inline void call(Function & f, Sequence & s) 121 { 122 f(BOOST_PP_ENUM(N,M,~)); 123 } 124 125 #else 126 127 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl128 static inline void call(Function & f, Sequence & /*s*/) 129 { 130 f(); 131 } 132 133 #endif 134 135 }; 136 137 #if N > 0 138 template <typename Function, class Sequence> 139 struct invoke_procedure_impl<Function,Sequence,N,true,true> 140 { 141 typedef void result_type; 142 143 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl144 static inline void call(Function & f, Sequence & s) 145 { 146 (that_ptr<typename mpl::front< 147 ft::parameter_types<Function> >::type 148 >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~)); 149 } 150 }; 151 #endif 152 153 #undef M 154 155 #define M(z,j,data) \ 156 typedef typename result_of::next< BOOST_PP_CAT(I,BOOST_PP_DEC(j)) \ 157 >::type I ## j ; \ 158 I##j i##j = fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j))); 159 160 template <typename Function, class Sequence> 161 struct invoke_procedure_impl<Function,Sequence,N,false,false> 162 { 163 typedef void result_type; 164 165 #if N > 0 166 167 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl168 static inline void call(Function & f, Sequence & s) 169 { 170 typedef typename result_of::begin<Sequence>::type I0; 171 I0 i0 = fusion::begin(s); 172 BOOST_PP_REPEAT_FROM_TO(1,N,M,~) 173 f( BOOST_PP_ENUM_PARAMS(N,*i) ); 174 } 175 176 #else 177 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl178 static inline void call(Function & f, Sequence & /*s*/) 179 { 180 f(); 181 } 182 183 #endif 184 185 }; 186 187 #if N > 0 188 template <typename Function, class Sequence> 189 struct invoke_procedure_impl<Function,Sequence,N,true,false> 190 { 191 typedef void result_type; 192 193 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callinvoke_procedure_impl194 static inline void call(Function & f, Sequence & s) 195 { 196 typedef typename result_of::begin<Sequence>::type I0; 197 I0 i0 = fusion::begin(s); 198 BOOST_PP_REPEAT_FROM_TO(1,N,M,~) 199 200 (that_ptr<typename mpl::front< 201 ft::parameter_types<Function> >::type 202 >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i)); 203 } 204 }; 205 #endif 206 207 #undef M 208 209 #undef N 210 #endif // defined(BOOST_PP_IS_ITERATING) 211 #endif 212 213