1 /////////////////////////////////////////////////////////////////////////////// 2 // extractor.hpp 3 // 4 // Copyright 2005 Eric Niebler. Distributed under the Boost 5 // Software License, Version 1.0. (See accompanying file 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 9 #define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 10 11 #include <boost/preprocessor/cat.hpp> 12 #include <boost/preprocessor/tuple/rem.hpp> 13 #include <boost/preprocessor/array/size.hpp> 14 #include <boost/preprocessor/array/data.hpp> 15 #include <boost/preprocessor/array/elem.hpp> 16 #include <boost/preprocessor/seq/to_array.hpp> 17 #include <boost/preprocessor/seq/transform.hpp> 18 #include <boost/preprocessor/repetition/enum_params.hpp> 19 #include <boost/preprocessor/repetition/enum_trailing.hpp> 20 #include <boost/preprocessor/repetition/enum_trailing_params.hpp> 21 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> 22 #include <boost/preprocessor/repetition/repeat.hpp> 23 #include <boost/preprocessor/repetition/repeat_from_to.hpp> 24 #include <boost/parameter/binding.hpp> 25 #include <boost/mpl/bool.hpp> 26 #include <boost/mpl/if.hpp> 27 #include <boost/mpl/eval_if.hpp> 28 #include <boost/mpl/apply.hpp> 29 #include <boost/type_traits/remove_const.hpp> 30 #include <boost/type_traits/remove_reference.hpp> 31 #include <boost/accumulators/accumulators_fwd.hpp> 32 #include <boost/accumulators/framework/parameters/accumulator.hpp> 33 34 namespace boost { namespace accumulators 35 { 36 37 namespace detail 38 { 39 template<typename AccumulatorSet, typename Feature> 40 struct accumulator_set_result 41 { 42 typedef typename as_feature<Feature>::type feature_type; 43 typedef typename mpl::apply< 44 typename boost::remove_const< 45 typename boost::remove_reference<AccumulatorSet>::type 46 >::type 47 , feature_type 48 >::type::result_type type; 49 }; 50 51 template<typename Args, typename Feature> 52 struct argument_pack_result 53 : accumulator_set_result< 54 typename boost::remove_reference< 55 typename parameter::binding< 56 typename boost::remove_const< 57 typename boost::remove_reference<Args>::type 58 >::type 59 , tag::accumulator 60 >::type 61 >::type 62 , Feature 63 > 64 { 65 }; 66 67 template<typename A, typename Feature> 68 struct extractor_result 69 : mpl::eval_if< 70 detail::is_accumulator_set<A> 71 , accumulator_set_result<A, Feature> 72 , argument_pack_result<A, Feature> 73 > 74 { 75 }; 76 77 template<typename Feature, typename AccumulatorSet> 78 typename extractor_result<AccumulatorSet, Feature>::type do_extract(AccumulatorSet const & acc,mpl::true_)79 do_extract(AccumulatorSet const &acc, mpl::true_) 80 { 81 typedef typename as_feature<Feature>::type feature_type; 82 return extract_result<feature_type>(acc); 83 } 84 85 template<typename Feature, typename Args> 86 typename extractor_result<Args, Feature>::type do_extract(Args const & args,mpl::false_)87 do_extract(Args const &args, mpl::false_) 88 { 89 typedef typename as_feature<Feature>::type feature_type; 90 return find_accumulator<feature_type>(args[accumulator]).result(args); 91 } 92 93 } // namespace detail 94 95 96 /////////////////////////////////////////////////////////////////////////////// 97 /// Extracts the result associated with Feature from the specified accumulator_set. 98 template<typename Feature> 99 struct extractor 100 { 101 typedef extractor<Feature> this_type; 102 103 /// The result meta-function for determining the return type of the extractor 104 template<typename F> 105 struct result; 106 107 template<typename A1> 108 struct result<this_type(A1)> 109 : detail::extractor_result<A1, Feature> 110 { 111 }; 112 113 /// Extract the result associated with Feature from the accumulator set 114 /// \param acc The accumulator set object from which to extract the result 115 template<typename Arg1> 116 typename detail::extractor_result<Arg1, Feature>::type operator ()boost::accumulators::extractor117 operator ()(Arg1 const &arg1) const 118 { 119 // Arg1 could be an accumulator_set or an argument pack containing 120 // an accumulator_set. Dispatch accordingly. 121 return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>()); 122 } 123 124 /// \overload 125 /// 126 /// \param a1 Optional named parameter to be passed to the accumulator's result() function. 127 template<typename AccumulatorSet, typename A1> 128 typename detail::extractor_result<AccumulatorSet, Feature>::type operator ()boost::accumulators::extractor129 operator ()(AccumulatorSet const &acc, A1 const &a1) const 130 { 131 BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); 132 typedef typename as_feature<Feature>::type feature_type; 133 return extract_result<feature_type>(acc, a1); 134 } 135 136 // ... other overloads generated by Boost.Preprocessor: 137 138 /// INTERNAL ONLY 139 /// 140 #define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \ 141 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ 142 struct result<this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> \ 143 : detail::extractor_result<A1, Feature> \ 144 {}; \ 145 template< \ 146 typename AccumulatorSet \ 147 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ 148 > \ 149 typename detail::extractor_result<AccumulatorSet, Feature>::type \ 150 operator ()( \ 151 AccumulatorSet const &acc \ 152 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ 153 ) const \ 154 { \ 155 BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); \ 156 typedef typename as_feature<Feature>::type feature_type; \ 157 return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\ 158 } 159 160 BOOST_PP_REPEAT_FROM_TO( 161 2 162 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) 163 , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP 164 , _ 165 ) 166 167 #undef BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP 168 169 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED 170 /// \overload 171 /// 172 template<typename AccumulatorSet, typename A1, typename A2, ...> 173 typename detail::extractor_result<AccumulatorSet, Feature>::type 174 operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...); 175 #endif 176 }; 177 178 }} // namespace boost::accumulators 179 180 /// INTERNAL ONLY 181 /// 182 #define BOOST_ACCUMULATORS_ARRAY_REM(Array) \ 183 BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array)) 184 185 /// INTERNAL ONLY 186 /// 187 #define BOOST_ACCUMULATORS_SEQ_REM(Seq) \ 188 BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq)) 189 190 /// INTERNAL ONLY 191 /// 192 #define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \ 193 T ## s 194 195 /// INTERNAL ONLY 196 /// 197 #define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \ 198 elem T ## s 199 200 /// INTERNAL ONLY 201 /// 202 #define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ 203 Tag::Feature< \ 204 BOOST_ACCUMULATORS_SEQ_REM( \ 205 BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \ 206 ) \ 207 > 208 209 /// INTERNAL ONLY 210 /// 211 #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq) \ 212 template< \ 213 BOOST_ACCUMULATORS_SEQ_REM( \ 214 BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \ 215 ) \ 216 , typename Arg1 \ 217 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ 218 > \ 219 typename boost::accumulators::detail::extractor_result< \ 220 Arg1 \ 221 , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ 222 >::type \ 223 Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \ 224 { \ 225 typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \ 226 return boost::accumulators::extractor<feature_type>()( \ 227 arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ 228 } 229 230 /// INTERNAL ONLY 231 /// 232 #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _) \ 233 BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \ 234 z \ 235 , n \ 236 , BOOST_PP_ARRAY_ELEM(0, _) \ 237 , BOOST_PP_ARRAY_ELEM(1, _) \ 238 , BOOST_PP_ARRAY_ELEM(2, _) \ 239 ) 240 241 #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq) \ 242 BOOST_PP_REPEAT( \ 243 BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \ 244 , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \ 245 , (3, (Tag, Feature, ParamSeq)) \ 246 ) 247 248 #endif 249