Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / accumulators / framework / accumulator_set.hpp @ 2486

History | View | Annotate | Download (14.7 kB)

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

    
34
namespace boost { namespace accumulators
35
{
36

    
37
namespace 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
///
106
template<typename Sample, typename Features, typename Weight>
107
struct 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

    
341
private:
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
353
template<typename Feature, typename AccumulatorSet>
354
typename mpl::apply<AccumulatorSet, Feature>::type &
355
find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
356
{
357
    return acc.template extract<Feature>();
358
}
359

    
360
/// \overload
361
template<typename Feature, typename AccumulatorSet>
362
typename mpl::apply<AccumulatorSet, Feature>::type const &
363
find_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

    
393
BOOST_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