Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:18

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // accumulator_set.hpp
0003 //
0004 //  Copyright 2005 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
0009 #define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
0010 
0011 #include <boost/version.hpp>
0012 #include <boost/mpl/bool.hpp>
0013 #include <boost/mpl/if.hpp>
0014 #include <boost/mpl/apply.hpp>
0015 #include <boost/mpl/assert.hpp>
0016 #include <boost/mpl/protect.hpp>
0017 #include <boost/mpl/identity.hpp>
0018 #include <boost/mpl/is_sequence.hpp>
0019 #include <boost/type_traits/is_same.hpp>
0020 #include <boost/type_traits/is_base_of.hpp>
0021 #include <boost/type_traits/remove_const.hpp>
0022 #include <boost/type_traits/remove_reference.hpp>
0023 #include <boost/core/enable_if.hpp>
0024 #include <boost/parameter/is_argument_pack.hpp>
0025 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
0026 #include <boost/preprocessor/repetition/enum_params.hpp>
0027 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0028 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0029 #include <boost/accumulators/accumulators_fwd.hpp>
0030 #include <boost/accumulators/framework/depends_on.hpp>
0031 #include <boost/accumulators/framework/accumulator_concept.hpp>
0032 #include <boost/accumulators/framework/parameters/accumulator.hpp>
0033 #include <boost/accumulators/framework/parameters/sample.hpp>
0034 #include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
0035 #include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
0036 #include <boost/fusion/include/any.hpp>
0037 #include <boost/fusion/include/find_if.hpp>
0038 #include <boost/fusion/include/for_each.hpp>
0039 #include <boost/fusion/include/filter_view.hpp>
0040 
0041 namespace boost { namespace accumulators
0042 {
0043 
0044 namespace detail
0045 {
0046     ///////////////////////////////////////////////////////////////////////////////
0047     // accumulator_visitor
0048     //   wrap a boost::parameter argument pack in a Fusion extractor object
0049     template<typename Args>
0050     struct accumulator_visitor
0051     {
0052         explicit accumulator_visitor(Args const &a)
0053           : args(a)
0054         {
0055         }
0056 
0057         accumulator_visitor(accumulator_visitor const &other)
0058           : args(other.args)
0059         {
0060         }
0061 
0062         template<typename Accumulator>
0063         void operator ()(Accumulator &accumulator) const
0064         {
0065             accumulator(this->args);
0066         }
0067 
0068     private:
0069         BOOST_DELETED_FUNCTION(accumulator_visitor &operator =(accumulator_visitor const &))
0070         Args const &args;
0071     };
0072 
0073     template<typename Args>
0074     inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
0075     {
0076         return accumulator_visitor<Args>(args);
0077     }
0078 
0079     ///////////////////////////////////////////////////////////////////////////////
0080     // accumulator_set_base
0081     struct accumulator_set_base
0082     {
0083     };
0084 
0085     ///////////////////////////////////////////////////////////////////////////////
0086     // is_accumulator_set
0087     template<typename T>
0088     struct is_accumulator_set
0089       : mpl::if_<
0090             boost::is_base_of<
0091                 accumulator_set_base
0092               , typename boost::remove_const<
0093                     typename boost::remove_reference<T>::type
0094                 >::type
0095             >
0096           , mpl::true_
0097           , mpl::false_
0098         >::type
0099     {
0100     };
0101 
0102     // function object that serialize an accumulator
0103     template<typename Archive>
0104     struct serialize_accumulator
0105     {
0106         serialize_accumulator(Archive & _ar, const unsigned int _file_version) :
0107             ar(_ar), file_version(_file_version)
0108         {}
0109 
0110         template<typename Accumulator>
0111         void operator ()(Accumulator &accumulator)
0112         {
0113             accumulator.serialize(ar, file_version);
0114         }
0115 
0116     private:
0117         Archive& ar;
0118         const unsigned int file_version;
0119     };
0120 
0121 } // namespace detail
0122 
0123 #ifdef _MSC_VER
0124 #pragma warning(push)
0125 #pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
0126 #endif
0127 
0128 ///////////////////////////////////////////////////////////////////////////////
0129 /// \brief A set of accumulators.
0130 ///
0131 /// accumulator_set resolves the dependencies between features and ensures that
0132 /// the accumulators in the set are updated in the proper order.
0133 ///
0134 /// acccumulator_set provides a general mechanism to visit the accumulators
0135 /// in the set in order, with or without a filter. You can also fetch a reference
0136 /// to an accumulator that corresponds to a feature.
0137 ///
0138 template<typename Sample, typename Features, typename Weight>
0139 struct accumulator_set
0140   : detail::accumulator_set_base
0141 {
0142     typedef Sample sample_type;     ///< The type of the samples that will be accumulated
0143     typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.
0144     typedef Weight weight_type;     ///< The type of the weight parameter. Must be a scalar. Defaults to void.
0145 
0146     /// INTERNAL ONLY
0147     ///
0148     typedef
0149         typename detail::make_accumulator_tuple<
0150             Features
0151           , Sample
0152           , Weight
0153         >::type
0154     accumulators_mpl_vector;
0155 
0156     // generate a fusion::list of accumulators
0157     /// INTERNAL ONLY
0158     ///
0159     typedef
0160         typename detail::meta::make_acc_list<
0161             accumulators_mpl_vector
0162         >::type
0163     accumulators_type;
0164 
0165     /// INTERNAL ONLY
0166     ///
0167     //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));
0168 
0169     ///////////////////////////////////////////////////////////////////////////////
0170     /// default-construct all contained accumulators
0171     accumulator_set()
0172       : accumulators(
0173             detail::make_acc_list(
0174                 accumulators_mpl_vector()
0175               , (boost::accumulators::accumulator = *this)
0176             )
0177         )
0178     {
0179         // Add-ref the Features that the user has specified
0180         this->template visit_if<detail::contains_feature_of_<Features> >(
0181             detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0182         );
0183     }
0184 
0185     /// \overload
0186     ///
0187     /// \param a1 Optional named parameter to be passed to all the accumulators
0188     template<typename A1>
0189     explicit accumulator_set(
0190         A1 const &a1
0191       , typename boost::enable_if<
0192             parameter::is_argument_pack<A1>
0193           , detail::_enabler
0194         >::type = detail::_enabler()
0195     ) : accumulators(
0196             detail::make_acc_list(
0197                 accumulators_mpl_vector()
0198               , (boost::accumulators::accumulator = *this, a1)
0199             )
0200         )
0201     {
0202         // Add-ref the Features that the user has specified
0203         this->template visit_if<detail::contains_feature_of_<Features> >(
0204             detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0205         );
0206     }
0207 
0208     /// \overload
0209     ///
0210     /// \param a1 Optional sample parameter to be passed to all the accumulators
0211     template<typename A1>
0212     explicit accumulator_set(
0213         A1 const &a1
0214       , typename boost::disable_if<
0215             parameter::is_argument_pack<A1>
0216           , detail::_enabler
0217         >::type = detail::_enabler()
0218     ) : accumulators(
0219             detail::make_acc_list(
0220                 accumulators_mpl_vector()
0221               , (
0222                     boost::accumulators::accumulator = *this
0223                   , boost::accumulators::sample = a1
0224                 )
0225             )
0226         )
0227     {
0228         // Add-ref the Features that the user has specified
0229         this->template visit_if<detail::contains_feature_of_<Features> >(
0230             detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0231         );
0232     }
0233 
0234     // ... other overloads generated by Boost.Preprocessor:
0235 
0236     /// INTERNAL ONLY
0237     ///
0238 #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _)                                \
0239     template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
0240     accumulator_set(                                                                    \
0241         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)                                \
0242       , typename boost::enable_if<                                                      \
0243             parameter::is_argument_pack<A0>                                             \
0244           , detail::_enabler                                                            \
0245         >::type = detail::_enabler()                                                    \
0246     ) : accumulators(                                                                   \
0247             detail::make_acc_list(                                                      \
0248                 accumulators_mpl_vector()                                               \
0249               , (                                                                       \
0250                     boost::accumulators::accumulator = *this                            \
0251                     BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                            \
0252                 )                                                                       \
0253             )                                                                           \
0254         )                                                                               \
0255     {                                                                                   \
0256         /* Add-ref the Features that the user has specified */                          \
0257         this->template visit_if<detail::contains_feature_of_<Features> >(               \
0258             detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)      \
0259         );                                                                              \
0260     }                                                                                   \
0261     template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
0262     accumulator_set(                                                                    \
0263         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)                                \
0264       , typename boost::disable_if<                                                     \
0265             parameter::is_argument_pack<A0>                                             \
0266           , detail::_enabler                                                            \
0267         >::type = detail::_enabler()                                                    \
0268     ) : accumulators(                                                                   \
0269             detail::make_acc_list(                                                      \
0270                 accumulators_mpl_vector()                                               \
0271               , (                                                                       \
0272                     boost::accumulators::accumulator = *this                            \
0273                   , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a)       \
0274                 )                                                                       \
0275             )                                                                           \
0276         )                                                                               \
0277     {                                                                                   \
0278         /* Add-ref the Features that the user has specified */                          \
0279         this->template visit_if<detail::contains_feature_of_<Features> >(               \
0280             detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)      \
0281         );                                                                              \
0282     }
0283 
0284     /// INTERNAL ONLY
0285     ///
0286     BOOST_PP_REPEAT_FROM_TO(
0287         2
0288       , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0289       , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
0290       , _
0291     )
0292 
0293     #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
0294     /// \overload
0295     ///
0296     template<typename A1, typename A2, ...>
0297     accumulator_set(A1 const &a1, A2 const &a2, ...);
0298     #endif
0299 
0300     // ... other overloads generated by Boost.Preprocessor below ...
0301 
0302     ///////////////////////////////////////////////////////////////////////////////
0303     /// Visitation
0304     /// \param func UnaryFunction which is invoked with each accumulator in turn.
0305     template<typename UnaryFunction>
0306     void visit(UnaryFunction const &func)
0307     {
0308         fusion::for_each(this->accumulators, func);
0309     }
0310 
0311     ///////////////////////////////////////////////////////////////////////////////
0312     /// Conditional visitation
0313     /// \param func UnaryFunction which is invoked with each accumulator in turn,
0314     ///     provided the accumulator satisfies the MPL predicate FilterPred.
0315     template<typename FilterPred, typename UnaryFunction>
0316     void visit_if(UnaryFunction const &func)
0317     {
0318         fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
0319         fusion::for_each(filtered_accs, func);
0320     }
0321     
0322     ///////////////////////////////////////////////////////////////////////////////
0323     /// The return type of the operator() overloads is void.
0324     typedef void result_type;
0325 
0326     ///////////////////////////////////////////////////////////////////////////////
0327     /// Accumulation
0328     /// \param a1 Optional named parameter to be passed to all the accumulators
0329     void operator ()()
0330     {
0331         this->visit(
0332             detail::make_accumulator_visitor(
0333                 boost::accumulators::accumulator = *this
0334             )
0335         );
0336     }
0337 
0338     // ... other overloads generated by Boost.Preprocessor:
0339 
0340     /// INTERNAL ONLY
0341     ///
0342 #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _)                              \
0343     template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
0344     void operator ()(                                                                   \
0345         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)                                \
0346       , typename boost::enable_if<                                                      \
0347             parameter::is_argument_pack<A0>                                             \
0348           , detail::_enabler                                                            \
0349         >::type = detail::_enabler()                                                    \
0350     )                                                                                   \
0351     {                                                                                   \
0352         this->visit(                                                                    \
0353             detail::make_accumulator_visitor(                                           \
0354                 (                                                                       \
0355                     boost::accumulators::accumulator = *this                            \
0356                     BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                            \
0357                 )                                                                       \
0358             )                                                                           \
0359         );                                                                              \
0360     }                                                                                   \
0361     template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
0362     void operator ()(                                                                   \
0363         BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)                                \
0364       , typename boost::disable_if<                                                     \
0365             parameter::is_argument_pack<A0>                                             \
0366           , detail::_enabler                                                            \
0367         >::type = detail::_enabler()                                                    \
0368     )                                                                                   \
0369     {                                                                                   \
0370         this->visit(                                                                    \
0371             detail::make_accumulator_visitor(                                           \
0372                 (                                                                       \
0373                     boost::accumulators::accumulator = *this                            \
0374                   , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a)       \
0375                 )                                                                       \
0376             )                                                                           \
0377         );                                                                              \
0378     }
0379 
0380     /// INTERNAL ONLY
0381     ///
0382     BOOST_PP_REPEAT_FROM_TO(
0383         1
0384       , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0385       , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
0386       , _
0387     )
0388 
0389     #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
0390     /// \overload
0391     ///
0392     template<typename A1, typename A2, ...>
0393     void operator ()(A1 const &a1, A2 const &a2, ...);
0394     #endif
0395 
0396     ///////////////////////////////////////////////////////////////////////////////
0397     /// Extraction
0398     template<typename Feature>
0399     struct apply
0400       : fusion::result_of::value_of<
0401             typename fusion::result_of::find_if<
0402                 accumulators_type
0403               , detail::matches_feature<Feature>
0404             >::type
0405         >
0406     {
0407     };
0408 
0409     ///////////////////////////////////////////////////////////////////////////////
0410     /// Extraction
0411     template<typename Feature>
0412     typename apply<Feature>::type &extract()
0413     {
0414         return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
0415     }
0416 
0417     /// \overload
0418     template<typename Feature>
0419     typename apply<Feature>::type const &extract() const
0420     {
0421         return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
0422     }
0423 
0424     ///////////////////////////////////////////////////////////////////////////////
0425     /// Drop
0426     template<typename Feature>
0427     void drop()
0428     {
0429         // You can only drop the features that you have specified explicitly
0430         typedef typename apply<Feature>::type the_accumulator;
0431         BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
0432 
0433         typedef
0434             typename feature_of<typename as_feature<Feature>::type>::type
0435         the_feature;
0436 
0437         (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
0438             .drop(boost::accumulators::accumulator = *this);
0439 
0440         // Also drop accumulators that this feature depends on
0441         typedef typename the_feature::dependencies dependencies;
0442         this->template visit_if<detail::contains_feature_of_<dependencies> >(
0443             detail::make_drop_visitor(boost::accumulators::accumulator = *this)
0444         );
0445     }
0446 
0447     // make the accumulator set serializeable
0448     template<class Archive>
0449     void serialize(Archive & ar, const unsigned int file_version)
0450     {
0451         detail::serialize_accumulator<Archive> serializer(ar, file_version);
0452         fusion::for_each(this->accumulators, serializer);
0453     }
0454 
0455 private:
0456 
0457     accumulators_type accumulators;
0458 };
0459 
0460 #ifdef _MSC_VER
0461 #pragma warning(pop)
0462 #endif
0463 
0464 ///////////////////////////////////////////////////////////////////////////////
0465 // find_accumulator
0466 //   find an accumulator in an accumulator_set corresponding to a feature
0467 template<typename Feature, typename AccumulatorSet>
0468 typename mpl::apply<AccumulatorSet, Feature>::type &
0469 find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
0470 {
0471     return acc.template extract<Feature>();
0472 }
0473 
0474 /// \overload
0475 template<typename Feature, typename AccumulatorSet>
0476 typename mpl::apply<AccumulatorSet, Feature>::type const &
0477 find_accumulator(AccumulatorSet const &acc)
0478 {
0479     return acc.template extract<Feature>();
0480 }
0481 
0482 template<typename Feature, typename AccumulatorSet>
0483 typename mpl::apply<AccumulatorSet, Feature>::type::result_type
0484 extract_result(AccumulatorSet const &acc)
0485 {
0486     return find_accumulator<Feature>(acc).result(
0487         boost::accumulators::accumulator = acc
0488     );
0489 }
0490 
0491 ///////////////////////////////////////////////////////////////////////////////
0492 // extract_result
0493 //   extract a result from an accumulator set
0494 /// INTERNAL ONLY
0495 ///
0496 #define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _)                      \
0497     template<                                                               \
0498         typename Feature                                                    \
0499       , typename AccumulatorSet                                             \
0500         BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                   \
0501     >                                                                       \
0502     typename mpl::apply<AccumulatorSet, Feature>::type::result_type         \
0503     extract_result(                                                         \
0504         AccumulatorSet const &acc                                           \
0505         BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a)           \
0506       , typename boost::enable_if<                                          \
0507             parameter::is_argument_pack<A0>                                 \
0508           , detail::_enabler                                                \
0509         >::type                                                             \
0510     )                                                                       \
0511     {                                                                       \
0512         return find_accumulator<Feature>(acc).result(                       \
0513             (                                                               \
0514                 boost::accumulators::accumulator = acc                      \
0515                 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                    \
0516             )                                                               \
0517         );                                                                  \
0518     }                                                                       \
0519     template<                                                               \
0520         typename Feature                                                    \
0521       , typename AccumulatorSet                                             \
0522         BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                   \
0523     >                                                                       \
0524     typename mpl::apply<AccumulatorSet, Feature>::type::result_type         \
0525     extract_result(                                                         \
0526         AccumulatorSet const &acc                                           \
0527         BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a)           \
0528       , typename boost::disable_if<                                         \
0529             parameter::is_argument_pack<A0>                                 \
0530           , detail::_enabler                                                \
0531         >::type                                                             \
0532     )                                                                       \
0533     {                                                                       \
0534         return find_accumulator<Feature>(acc).result((                      \
0535             boost::accumulators::accumulator = acc                          \
0536           , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a)   \
0537         ));                                                                 \
0538     }
0539 
0540 BOOST_PP_REPEAT_FROM_TO(
0541     1
0542   , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0543   , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
0544   , _
0545 )
0546 
0547 }} // namespace boost::accumulators
0548 
0549 #endif