PageRenderTime 19ms CodeModel.GetById 1ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/accumulators/framework/accumulator_set.hpp

http://hadesmem.googlecode.com/
C++ Header | 401 lines | 269 code | 48 blank | 84 comment | 0 complexity | c72c5e2f2779fb2d8d6078c1b4a90d5e MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2// accumulator_set.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_ACCUMULATOR_SET_HPP_EAN_28_10_2005
  9#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
 10
 11#include <boost/version.hpp>
 12#include <boost/mpl/apply.hpp>
 13#include <boost/mpl/assert.hpp>
 14#include <boost/mpl/protect.hpp>
 15#include <boost/mpl/identity.hpp>
 16#include <boost/mpl/is_sequence.hpp>
 17#include <boost/type_traits/is_same.hpp>
 18#include <boost/type_traits/is_base_and_derived.hpp>
 19#include <boost/parameter/parameters.hpp>
 20#include <boost/preprocessor/repetition/repeat_from_to.hpp>
 21#include <boost/preprocessor/repetition/enum_binary_params.hpp>
 22#include <boost/accumulators/accumulators_fwd.hpp>
 23#include <boost/accumulators/framework/depends_on.hpp>
 24#include <boost/accumulators/framework/accumulator_concept.hpp>
 25#include <boost/accumulators/framework/parameters/accumulator.hpp>
 26#include <boost/accumulators/framework/parameters/sample.hpp>
 27#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
 28#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
 29#include <boost/fusion/include/any.hpp>
 30#include <boost/fusion/include/find_if.hpp>
 31#include <boost/fusion/include/for_each.hpp>
 32#include <boost/fusion/include/filter_view.hpp>
 33
 34namespace boost { namespace accumulators
 35{
 36
 37namespace detail
 38{
 39    ///////////////////////////////////////////////////////////////////////////////
 40    // accumulator_visitor
 41    //   wrap a boost::parameter argument pack in a Fusion extractor object
 42    template<typename Args>
 43    struct accumulator_visitor
 44    {
 45        explicit accumulator_visitor(Args const &a)
 46          : args(a)
 47        {
 48        }
 49
 50        template<typename Accumulator>
 51        void operator ()(Accumulator &accumulator) const
 52        {
 53            accumulator(this->args);
 54        }
 55
 56    private:
 57        accumulator_visitor &operator =(accumulator_visitor const &);
 58        Args const &args;
 59    };
 60
 61    template<typename Args>
 62    inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
 63    {
 64        return accumulator_visitor<Args>(args);
 65    }
 66
 67    typedef
 68        parameter::parameters<
 69            parameter::required<tag::accumulator>
 70          , parameter::optional<tag::sample>
 71          // ... and others which are not specified here...
 72        >
 73    accumulator_params;
 74
 75    ///////////////////////////////////////////////////////////////////////////////
 76    // accumulator_set_base
 77    struct accumulator_set_base
 78    {
 79    };
 80
 81    ///////////////////////////////////////////////////////////////////////////////
 82    // is_accumulator_set
 83    template<typename T>
 84    struct is_accumulator_set
 85      : is_base_and_derived<accumulator_set_base, T>
 86    {
 87    };
 88
 89} // namespace detail
 90
 91#ifdef _MSC_VER
 92#pragma warning(push)
 93#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
 94#endif
 95
 96///////////////////////////////////////////////////////////////////////////////
 97/// \brief A set of accumulators.
 98///
 99/// accumulator_set resolves the dependencies between features and ensures that
100/// the accumulators in the set are updated in the proper order.
101///
102/// acccumulator_set provides a general mechanism to visit the accumulators
103/// in the set in order, with or without a filter. You can also fetch a reference
104/// to an accumulator that corresponds to a feature.
105///
106template<typename Sample, typename Features, typename Weight>
107struct accumulator_set
108  : detail::accumulator_set_base
109{
110    typedef Sample sample_type;     ///< The type of the samples that will be accumulated
111    typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.
112    typedef Weight weight_type;     ///< The type of the weight parameter. Must be a scalar. Defaults to void.
113
114    /// INTERNAL ONLY
115    ///
116    typedef
117        typename detail::make_accumulator_tuple<
118            Features
119          , Sample
120          , Weight
121        >::type
122    accumulators_mpl_vector;
123
124    // generate a fusion::list of accumulators
125    /// INTERNAL ONLY
126    ///
127    typedef
128        typename detail::meta::make_acc_list<
129            accumulators_mpl_vector
130        >::type
131    accumulators_type;
132
133    /// INTERNAL ONLY
134    ///
135    //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));
136
137    ///////////////////////////////////////////////////////////////////////////////
138    /// default-construct all contained accumulators
139    accumulator_set()
140      : accumulators(
141            detail::make_acc_list(
142                accumulators_mpl_vector()
143              , detail::accumulator_params()(*this)
144            )
145        )
146    {
147        // Add-ref the Features that the user has specified
148        this->template visit_if<detail::contains_feature_of_<Features> >(
149            detail::make_add_ref_visitor(detail::accumulator_params()(*this))
150        );
151    }
152
153    /// \overload
154    ///
155    /// \param a1 Optional named parameter to be passed to all the accumulators
156    template<typename A1>
157    explicit accumulator_set(A1 const &a1)
158      : accumulators(
159            detail::make_acc_list(
160                accumulators_mpl_vector()
161              , detail::accumulator_params()(*this, a1)
162            )
163        )
164    {
165        // Add-ref the Features that the user has specified
166        this->template visit_if<detail::contains_feature_of_<Features> >(
167            detail::make_add_ref_visitor(detail::accumulator_params()(*this))
168        );
169    }
170
171    // ... other overloads generated by Boost.Preprocessor:
172
173    /// INTERNAL ONLY
174    ///
175#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _)                                \
176    template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
177    accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a))                   \
178      : accumulators(                                                                   \
179            detail::make_acc_list(                                                      \
180                accumulators_mpl_vector()                                               \
181              , detail::accumulator_params()(                                           \
182                    *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                      \
183                )                                                                       \
184            )                                                                           \
185        )                                                                               \
186    {                                                                                   \
187        /* Add-ref the Features that the user has specified */                          \
188        this->template visit_if<detail::contains_feature_of_<Features> >(               \
189            detail::make_add_ref_visitor(detail::accumulator_params()(*this))           \
190        );                                                                              \
191    }
192
193    /// INTERNAL ONLY
194    ///
195    BOOST_PP_REPEAT_FROM_TO(
196        2
197      , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
198      , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
199      , _
200    )
201
202    #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
203    /// \overload
204    ///
205    template<typename A1, typename A2, ...>
206    accumulator_set(A1 const &a1, A2 const &a2, ...);
207    #endif
208
209    // ... other overloads generated by Boost.Preprocessor below ...
210
211    ///////////////////////////////////////////////////////////////////////////////
212    /// Visitation
213    /// \param func UnaryFunction which is invoked with each accumulator in turn.
214    template<typename UnaryFunction>
215    void visit(UnaryFunction const &func)
216    {
217        fusion::for_each(this->accumulators, func);
218    }
219
220    ///////////////////////////////////////////////////////////////////////////////
221    /// Conditional visitation
222    /// \param func UnaryFunction which is invoked with each accumulator in turn,
223    ///     provided the accumulator satisfies the MPL predicate FilterPred.
224    template<typename FilterPred, typename UnaryFunction>
225    void visit_if(UnaryFunction const &func)
226    {
227        fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
228        fusion::for_each(filtered_accs, func);
229    }
230    
231    ///////////////////////////////////////////////////////////////////////////////
232    /// The return type of the operator() overloads is void.
233    typedef void result_type;
234
235    ///////////////////////////////////////////////////////////////////////////////
236    /// Accumulation
237    /// \param a1 Optional named parameter to be passed to all the accumulators
238    void operator ()()
239    {
240        this->visit(
241            detail::make_accumulator_visitor(
242                detail::accumulator_params()(*this)
243            )
244        );
245    }
246
247    template<typename A1>
248    void operator ()(A1 const &a1)
249    {
250        this->visit(
251            detail::make_accumulator_visitor(
252                detail::accumulator_params()(*this, a1)
253            )
254        );
255    }
256
257    // ... other overloads generated by Boost.Preprocessor:
258
259    /// INTERNAL ONLY
260    ///
261#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _)                              \
262    template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
263    void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a))                  \
264    {                                                                                   \
265        this->visit(                                                                    \
266            detail::make_accumulator_visitor(                                           \
267                detail::accumulator_params()(                                           \
268                    *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                      \
269                )                                                                       \
270            )                                                                           \
271        );                                                                              \
272    }
273
274    /// INTERNAL ONLY
275    ///
276    BOOST_PP_REPEAT_FROM_TO(
277        2
278      , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
279      , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
280      , _
281    )
282
283    #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
284    /// \overload
285    ///
286    template<typename A1, typename A2, ...>
287    void operator ()(A1 const &a1, A2 const &a2, ...);
288    #endif
289
290    ///////////////////////////////////////////////////////////////////////////////
291    /// Extraction
292    template<typename Feature>
293    struct apply
294      : fusion::result_of::value_of<
295            typename fusion::result_of::find_if<
296                accumulators_type
297              , detail::matches_feature<Feature>
298            >::type
299        >
300    {
301    };
302
303    ///////////////////////////////////////////////////////////////////////////////
304    /// Extraction
305    template<typename Feature>
306    typename apply<Feature>::type &extract()
307    {
308        return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
309    }
310
311    /// \overload
312    template<typename Feature>
313    typename apply<Feature>::type const &extract() const
314    {
315        return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
316    }
317
318    ///////////////////////////////////////////////////////////////////////////////
319    /// Drop
320    template<typename Feature>
321    void drop()
322    {
323        // You can only drop the features that you have specified explicitly
324        typedef typename apply<Feature>::type the_accumulator;
325        BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
326
327        typedef
328            typename feature_of<typename as_feature<Feature>::type>::type
329        the_feature;
330
331        (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
332            .drop(detail::accumulator_params()(*this));
333
334        // Also drop accumulators that this feature depends on
335        typedef typename the_feature::dependencies dependencies;
336        this->template visit_if<detail::contains_feature_of_<dependencies> >(
337            detail::make_drop_visitor(detail::accumulator_params()(*this))
338        );
339    }
340
341private:
342
343    accumulators_type accumulators;
344};
345
346#ifdef _MSC_VER
347#pragma warning(pop)
348#endif
349
350///////////////////////////////////////////////////////////////////////////////
351// find_accumulator
352//   find an accumulator in an accumulator_set corresponding to a feature
353template<typename Feature, typename AccumulatorSet>
354typename mpl::apply<AccumulatorSet, Feature>::type &
355find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
356{
357    return acc.template extract<Feature>();
358}
359
360/// \overload
361template<typename Feature, typename AccumulatorSet>
362typename mpl::apply<AccumulatorSet, Feature>::type const &
363find_accumulator(AccumulatorSet const &acc)
364{
365    return acc.template extract<Feature>();
366}
367
368///////////////////////////////////////////////////////////////////////////////
369// extract_result
370//   extract a result from an accumulator set
371/// INTERNAL ONLY
372///
373#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _)                      \
374    template<                                                               \
375        typename Feature                                                    \
376      , typename AccumulatorSet                                             \
377        BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                   \
378    >                                                                       \
379    typename mpl::apply<AccumulatorSet, Feature>::type::result_type         \
380    extract_result(                                                         \
381        AccumulatorSet const &acc                                           \
382        BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a)           \
383    )                                                                       \
384    {                                                                       \
385        return find_accumulator<Feature>(acc).result(                       \
386            detail::accumulator_params()(                                   \
387                acc                                                         \
388                BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                    \
389            )                                                               \
390        );                                                                  \
391    }
392
393BOOST_PP_REPEAT(
394    BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
395  , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
396  , _
397)
398
399}} // namespace boost::accumulators
400
401#endif