diff options
Diffstat (limited to 'boost/accumulators/framework/accumulator_set.hpp')
-rw-r--r-- | boost/accumulators/framework/accumulator_set.hpp | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/boost/accumulators/framework/accumulator_set.hpp b/boost/accumulators/framework/accumulator_set.hpp new file mode 100644 index 0000000000..ed1ceb1afa --- /dev/null +++ b/boost/accumulators/framework/accumulator_set.hpp @@ -0,0 +1,401 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_set.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_ACCUMULATOR_SET_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005 + +#include <boost/version.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/protect.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/parameter/parameters.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/framework/accumulator_concept.hpp> +#include <boost/accumulators/framework/parameters/accumulator.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp> +#include <boost/fusion/include/any.hpp> +#include <boost/fusion/include/find_if.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/fusion/include/filter_view.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + /////////////////////////////////////////////////////////////////////////////// + // accumulator_visitor + // wrap a boost::parameter argument pack in a Fusion extractor object + template<typename Args> + struct accumulator_visitor + { + explicit accumulator_visitor(Args const &a) + : args(a) + { + } + + template<typename Accumulator> + void operator ()(Accumulator &accumulator) const + { + accumulator(this->args); + } + + private: + accumulator_visitor &operator =(accumulator_visitor const &); + Args const &args; + }; + + template<typename Args> + inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args) + { + return accumulator_visitor<Args>(args); + } + + typedef + parameter::parameters< + parameter::required<tag::accumulator> + , parameter::optional<tag::sample> + // ... and others which are not specified here... + > + accumulator_params; + + /////////////////////////////////////////////////////////////////////////////// + // accumulator_set_base + struct accumulator_set_base + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // is_accumulator_set + template<typename T> + struct is_accumulator_set + : is_base_and_derived<accumulator_set_base, T> + { + }; + +} // namespace detail + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list +#endif + +/////////////////////////////////////////////////////////////////////////////// +/// \brief A set of accumulators. +/// +/// accumulator_set resolves the dependencies between features and ensures that +/// the accumulators in the set are updated in the proper order. +/// +/// acccumulator_set provides a general mechanism to visit the accumulators +/// in the set in order, with or without a filter. You can also fetch a reference +/// to an accumulator that corresponds to a feature. +/// +template<typename Sample, typename Features, typename Weight> +struct accumulator_set + : detail::accumulator_set_base +{ + typedef Sample sample_type; ///< The type of the samples that will be accumulated + typedef Features features_type; ///< An MPL sequence of the features that should be accumulated. + typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void. + + /// INTERNAL ONLY + /// + typedef + typename detail::make_accumulator_tuple< + Features + , Sample + , Weight + >::type + accumulators_mpl_vector; + + // generate a fusion::list of accumulators + /// INTERNAL ONLY + /// + typedef + typename detail::meta::make_acc_list< + accumulators_mpl_vector + >::type + accumulators_type; + + /// INTERNAL ONLY + /// + //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>)); + + /////////////////////////////////////////////////////////////////////////////// + /// default-construct all contained accumulators + accumulator_set() + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if<detail::contains_feature_of_<Features> >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + /// \overload + /// + /// \param a1 Optional named parameter to be passed to all the accumulators + template<typename A1> + explicit accumulator_set(A1 const &a1) + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this, a1) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if<detail::contains_feature_of_<Features> >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \ + template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ + accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + : accumulators( \ + detail::make_acc_list( \ + accumulators_mpl_vector() \ + , detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ) \ + { \ + /* Add-ref the Features that the user has specified */ \ + this->template visit_if<detail::contains_feature_of_<Features> >( \ + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template<typename A1, typename A2, ...> + accumulator_set(A1 const &a1, A2 const &a2, ...); + #endif + + // ... other overloads generated by Boost.Preprocessor below ... + + /////////////////////////////////////////////////////////////////////////////// + /// Visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn. + template<typename UnaryFunction> + void visit(UnaryFunction const &func) + { + fusion::for_each(this->accumulators, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Conditional visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn, + /// provided the accumulator satisfies the MPL predicate FilterPred. + template<typename FilterPred, typename UnaryFunction> + void visit_if(UnaryFunction const &func) + { + fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators); + fusion::for_each(filtered_accs, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// The return type of the operator() overloads is void. + typedef void result_type; + + /////////////////////////////////////////////////////////////////////////////// + /// Accumulation + /// \param a1 Optional named parameter to be passed to all the accumulators + void operator ()() + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this) + ) + ); + } + + template<typename A1> + void operator ()(A1 const &a1) + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this, a1) + ) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \ + template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ + void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + { \ + this->visit( \ + detail::make_accumulator_visitor( \ + detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template<typename A1, typename A2, ...> + void operator ()(A1 const &a1, A2 const &a2, ...); + #endif + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template<typename Feature> + struct apply + : fusion::result_of::value_of< + typename fusion::result_of::find_if< + accumulators_type + , detail::matches_feature<Feature> + >::type + > + { + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template<typename Feature> + typename apply<Feature>::type &extract() + { + return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators); + } + + /// \overload + template<typename Feature> + typename apply<Feature>::type const &extract() const + { + return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Drop + template<typename Feature> + void drop() + { + // You can only drop the features that you have specified explicitly + typedef typename apply<Feature>::type the_accumulator; + BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>)); + + typedef + typename feature_of<typename as_feature<Feature>::type>::type + the_feature; + + (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators)) + .drop(detail::accumulator_params()(*this)); + + // Also drop accumulators that this feature depends on + typedef typename the_feature::dependencies dependencies; + this->template visit_if<detail::contains_feature_of_<dependencies> >( + detail::make_drop_visitor(detail::accumulator_params()(*this)) + ); + } + +private: + + accumulators_type accumulators; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// find_accumulator +// find an accumulator in an accumulator_set corresponding to a feature +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type & +find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet)) +{ + return acc.template extract<Feature>(); +} + +/// \overload +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type const & +find_accumulator(AccumulatorSet const &acc) +{ + return acc.template extract<Feature>(); +} + +/////////////////////////////////////////////////////////////////////////////// +// extract_result +// extract a result from an accumulator set +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \ + template< \ + typename Feature \ + , typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename mpl::apply<AccumulatorSet, Feature>::type::result_type \ + extract_result( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ) \ + { \ + return find_accumulator<Feature>(acc).result( \ + detail::accumulator_params()( \ + acc \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ); \ + } + +BOOST_PP_REPEAT( + BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN + , _ +) + +}} // namespace boost::accumulators + +#endif |