EVOLUTION-MANAGER
Edit File: extractor.hpp
/////////////////////////////////////////////////////////////////////////////// // extractor.hpp // // Copyright 2005 Eric Niebler. Distributed under 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) #ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 #define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/tuple/rem.hpp> #include <boost/preprocessor/array/size.hpp> #include <boost/preprocessor/array/data.hpp> #include <boost/preprocessor/array/elem.hpp> #include <boost/preprocessor/seq/to_array.hpp> #include <boost/preprocessor/seq/transform.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_trailing.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/parameter/binding.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/apply.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/accumulators/accumulators_fwd.hpp> #include <boost/accumulators/framework/parameters/accumulator.hpp> namespace boost { namespace accumulators { namespace detail { template<typename AccumulatorSet, typename Feature> struct accumulator_set_result { typedef typename as_feature<Feature>::type feature_type; typedef typename mpl::apply< typename boost::remove_const< typename boost::remove_reference<AccumulatorSet>::type >::type , feature_type >::type::result_type type; }; template<typename Args, typename Feature> struct argument_pack_result : accumulator_set_result< typename boost::remove_reference< typename parameter::binding< typename boost::remove_const< typename boost::remove_reference<Args>::type >::type , tag::accumulator >::type >::type , Feature > { }; template<typename A, typename Feature> struct extractor_result : mpl::eval_if< detail::is_accumulator_set<A> , accumulator_set_result<A, Feature> , argument_pack_result<A, Feature> > { }; template<typename Feature, typename AccumulatorSet> typename extractor_result<AccumulatorSet, Feature>::type do_extract(AccumulatorSet const &acc, mpl::true_) { typedef typename as_feature<Feature>::type feature_type; return extract_result<feature_type>(acc); } template<typename Feature, typename Args> typename extractor_result<Args, Feature>::type do_extract(Args const &args, mpl::false_) { typedef typename as_feature<Feature>::type feature_type; return find_accumulator<feature_type>(args[accumulator]).result(args); } } // namespace detail /////////////////////////////////////////////////////////////////////////////// /// Extracts the result associated with Feature from the specified accumulator_set. template<typename Feature> struct extractor { typedef extractor<Feature> this_type; /// The result meta-function for determining the return type of the extractor template<typename F> struct result; template<typename A1> struct result<this_type(A1)> : detail::extractor_result<A1, Feature> { }; /// Extract the result associated with Feature from the accumulator set /// \param acc The accumulator set object from which to extract the result template<typename Arg1> typename detail::extractor_result<Arg1, Feature>::type operator ()(Arg1 const &arg1) const { // Arg1 could be an accumulator_set or an argument pack containing // an accumulator_set. Dispatch accordingly. return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>()); } /// \overload /// /// \param a1 Optional named parameter to be passed to the accumulator's result() function. template<typename AccumulatorSet, typename A1> typename detail::extractor_result<AccumulatorSet, Feature>::type operator ()(AccumulatorSet const &acc, A1 const &a1) const { BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); typedef typename as_feature<Feature>::type feature_type; return extract_result<feature_type>(acc, a1); } // ... other overloads generated by Boost.Preprocessor: /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \ template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ struct result<this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> \ : detail::extractor_result<A1, Feature> \ {}; \ template< \ typename AccumulatorSet \ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ > \ typename detail::extractor_result<AccumulatorSet, Feature>::type \ operator ()( \ AccumulatorSet const &acc \ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ ) const \ { \ BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); \ typedef typename as_feature<Feature>::type feature_type; \ return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\ } BOOST_PP_REPEAT_FROM_TO( 2 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP , _ ) #undef BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED /// \overload /// template<typename AccumulatorSet, typename A1, typename A2, ...> typename detail::extractor_result<AccumulatorSet, Feature>::type operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...); #endif }; }} // namespace boost::accumulators /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_ARRAY_REM(Array) \ BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array)) /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_SEQ_REM(Seq) \ BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq)) /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \ T ## s /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \ elem T ## s /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ Tag::Feature< \ BOOST_ACCUMULATORS_SEQ_REM( \ BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \ ) \ > /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq) \ template< \ BOOST_ACCUMULATORS_SEQ_REM( \ BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \ ) \ , typename Arg1 \ BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ > \ typename boost::accumulators::detail::extractor_result< \ Arg1 \ , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ >::type \ Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \ { \ typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \ return boost::accumulators::extractor<feature_type>()( \ arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ } /// INTERNAL ONLY /// #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _) \ BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \ z \ , n \ , BOOST_PP_ARRAY_ELEM(0, _) \ , BOOST_PP_ARRAY_ELEM(1, _) \ , BOOST_PP_ARRAY_ELEM(2, _) \ ) #define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq) \ BOOST_PP_REPEAT( \ BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \ , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \ , (3, (Tag, Feature, ParamSeq)) \ ) #endif