You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
229 lines
10 KiB
229 lines
10 KiB
/////////////////////////////////////////////////////////////////////////////// |
|
// 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/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_params.hpp> |
|
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> |
|
#include <boost/parameter/binding.hpp> |
|
#include <boost/mpl/apply.hpp> |
|
#include <boost/mpl/eval_if.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<AccumulatorSet, feature_type>::type::result_type type; |
|
}; |
|
|
|
template<typename Args, typename Feature> |
|
struct argument_pack_result |
|
: accumulator_set_result< |
|
typename remove_reference< |
|
typename parameter::binding<Args, 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 |
|
, _ |
|
) |
|
|
|
#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 |
|
}; |
|
|
|
/// 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)) \ |
|
) |
|
|
|
}} // namespace boost::accumulators |
|
|
|
#endif
|
|
|