Statistics
| Revision:

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

History | View | Annotate | Download (14.5 kB)

1
///////////////////////////////////////////////////////////////////////////////
2
// depends_on.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_DEPENDS_ON_HPP_EAN_28_10_2005
9
#define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
10

    
11
#include <boost/version.hpp>
12
#include <boost/mpl/end.hpp>
13
#include <boost/mpl/map.hpp>
14
#include <boost/mpl/set.hpp>
15
#include <boost/mpl/copy.hpp>
16
#include <boost/mpl/fold.hpp>
17
#include <boost/mpl/size.hpp>
18
#include <boost/mpl/sort.hpp>
19
#include <boost/mpl/insert.hpp>
20
#include <boost/mpl/assert.hpp>
21
#include <boost/mpl/remove.hpp>
22
#include <boost/mpl/vector.hpp>
23
#include <boost/mpl/inherit.hpp>
24
#include <boost/mpl/identity.hpp>
25
#include <boost/mpl/equal_to.hpp>
26
#include <boost/mpl/contains.hpp>
27
#include <boost/mpl/transform.hpp>
28
#include <boost/mpl/is_sequence.hpp>
29
#include <boost/mpl/placeholders.hpp>
30
#include <boost/mpl/insert_range.hpp>
31
#include <boost/mpl/back_inserter.hpp>
32
#include <boost/mpl/transform_view.hpp>
33
#include <boost/mpl/inherit_linearly.hpp>
34
#include <boost/type_traits/is_base_and_derived.hpp>
35
#include <boost/preprocessor/repetition/repeat.hpp>
36
#include <boost/preprocessor/repetition/enum_params.hpp>
37
#include <boost/preprocessor/facilities/intercept.hpp>
38
#include <boost/accumulators/accumulators_fwd.hpp>
39
#include <boost/fusion/include/next.hpp>
40
#include <boost/fusion/include/equal_to.hpp>
41
#include <boost/fusion/include/value_of.hpp>
42
#include <boost/fusion/include/mpl.hpp>
43
#include <boost/fusion/include/end.hpp>
44
#include <boost/fusion/include/begin.hpp>
45
#include <boost/fusion/include/cons.hpp>
46

    
47
namespace boost { namespace accumulators
48
{
49
    ///////////////////////////////////////////////////////////////////////////
50
    // as_feature
51
    template<typename Feature>
52
    struct as_feature
53
    {
54
        typedef Feature type;
55
    };
56

    
57
    ///////////////////////////////////////////////////////////////////////////
58
    // weighted_feature
59
    template<typename Feature>
60
    struct as_weighted_feature
61
    {
62
        typedef Feature type;
63
    };
64

    
65
    ///////////////////////////////////////////////////////////////////////////
66
    // feature_of
67
    template<typename Feature>
68
    struct feature_of
69
    {
70
        typedef Feature type;
71
    };
72

    
73
    namespace detail
74
    {
75
        ///////////////////////////////////////////////////////////////////////////
76
        // feature_tag
77
        template<typename Accumulator>
78
        struct feature_tag
79
        {
80
            typedef typename Accumulator::feature_tag type;
81
        };
82

    
83
        template<typename Feature>
84
        struct undroppable
85
        {
86
            typedef Feature type;
87
        };
88

    
89
        template<typename Feature>
90
        struct undroppable<tag::droppable<Feature> >
91
        {
92
            typedef Feature type;
93
        };
94

    
95
        // For the purpose of determining whether one feature depends on another,
96
        // disregard whether the feature is droppable or not.
97
        template<typename A, typename B>
98
        struct is_dependent_on
99
          : is_base_and_derived<
100
                typename feature_of<typename undroppable<B>::type>::type
101
              , typename undroppable<A>::type
102
            >
103
        {};
104

    
105
        template<typename Feature>
106
        struct dependencies_of
107
        {
108
            typedef typename Feature::dependencies type;
109
        };
110

    
111
        // Should use mpl::insert_range, but doesn't seem to work with mpl sets
112
        template<typename Set, typename Range>
113
        struct set_insert_range
114
          : mpl::fold<
115
                Range
116
              , Set
117
              , mpl::insert<mpl::_1, mpl::_2>
118
            >
119
        {};
120

    
121
        template<typename Features>
122
        struct collect_abstract_features
123
          : mpl::fold<
124
                Features
125
              , mpl::set0<>
126
              , set_insert_range<
127
                    mpl::insert<mpl::_1, feature_of<mpl::_2> >
128
                  , collect_abstract_features<dependencies_of<mpl::_2> >
129
                >
130
            >
131
        {};
132

    
133
        template<typename Features>
134
        struct depends_on_base
135
          : mpl::inherit_linearly<
136
                typename mpl::sort<
137
                    typename mpl::copy<
138
                        typename collect_abstract_features<Features>::type
139
                      , mpl::back_inserter<mpl::vector0<> >
140
                    >::type
141
                  , is_dependent_on<mpl::_1, mpl::_2>
142
                >::type
143
                // Don't inherit multiply from a feature
144
              , mpl::if_<
145
                    is_dependent_on<mpl::_1, mpl::_2>
146
                  , mpl::_1
147
                  , mpl::inherit<mpl::_1, mpl::_2>
148
                >
149
            >::type
150
        {
151
        };
152
    }
153

    
154
    ///////////////////////////////////////////////////////////////////////////
155
    /// depends_on
156
    template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
157
    struct depends_on
158
      : detail::depends_on_base<
159
            typename mpl::transform<
160
                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
161
              , as_feature<mpl::_1>
162
            >::type
163
        >
164
    {
165
        typedef mpl::false_ is_weight_accumulator;
166
        typedef
167
            typename mpl::transform<
168
                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
169
              , as_feature<mpl::_1>
170
            >::type
171
        dependencies;
172
    };
173

    
174
    namespace detail
175
    {
176
        template<typename Feature>
177
        struct matches_feature
178
        {
179
            template<typename Accumulator>
180
            struct apply
181
              : is_same<
182
                    typename feature_of<typename as_feature<Feature>::type>::type
183
                  , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type
184
                >
185
            {};
186
        };
187

    
188
        template<typename Features, typename Accumulator>
189
        struct contains_feature_of
190
        {
191
            typedef
192
                mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >
193
            features_list;
194

    
195
            typedef
196
                typename feature_of<typename feature_tag<Accumulator>::type>::type
197
            the_feature;
198

    
199
            typedef
200
                typename mpl::contains<features_list, the_feature>::type
201
            type;
202
        };
203

    
204
        // This is to work around a bug in early versions of Fusion which caused
205
        // a compile error if contains_feature_of<List, mpl::_> is used as a
206
        // predicate to fusion::find_if
207
        template<typename Features>
208
        struct contains_feature_of_
209
        {
210
            template<typename Accumulator>
211
            struct apply
212
              : contains_feature_of<Features, Accumulator>
213
            {};
214
        };
215

    
216
        template<
217
            typename First
218
          , typename Last
219
          , bool is_empty = fusion::result_of::equal_to<First, Last>::value
220
        >
221
        struct build_acc_list;
222

    
223
        template<typename First, typename Last>
224
        struct build_acc_list<First, Last, true>
225
        {
226
            typedef fusion::nil type;
227

    
228
            template<typename Args>
229
            static fusion::nil
230
            call(Args const &, First const&, Last const&)
231
            {
232
                return fusion::nil();
233
            }
234
        };
235

    
236
        template<typename First, typename Last>
237
        struct build_acc_list<First, Last, false>
238
        {
239
            typedef
240
                build_acc_list<typename fusion::result_of::next<First>::type, Last>
241
            next_build_acc_list;
242

    
243
            typedef fusion::cons<
244
                typename fusion::result_of::value_of<First>::type
245
              , typename next_build_acc_list::type>
246
            type;
247

    
248
            template<typename Args>
249
            static type
250
            call(Args const &args, First const& f, Last const& l)
251
            {
252
                return type(args, next_build_acc_list::call(args, fusion::next(f), l));
253
            }
254
        };
255

    
256
        namespace meta
257
        {
258
            template<typename Sequence>
259
            struct make_acc_list
260
              : build_acc_list<
261
                    typename fusion::result_of::begin<Sequence>::type
262
                  , typename fusion::result_of::end<Sequence>::type
263
                >
264
            {};
265
        }
266

    
267
        template<typename Sequence, typename Args>
268
        typename meta::make_acc_list<Sequence>::type
269
        make_acc_list(Sequence const &seq, Args const &args)
270
        {
271
            return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
272
        }
273

    
274
        ///////////////////////////////////////////////////////////////////////////
275
        // checked_as_weighted_feature
276
        template<typename Feature>
277
        struct checked_as_weighted_feature
278
        {
279
            typedef typename as_feature<Feature>::type feature_type;
280
            typedef typename as_weighted_feature<feature_type>::type type;
281
            // weighted and non-weighted flavors should provide the same feature.
282
            BOOST_MPL_ASSERT((
283
                is_same<
284
                    typename feature_of<feature_type>::type
285
                  , typename feature_of<type>::type
286
                >
287
            ));
288
        };
289

    
290
        ///////////////////////////////////////////////////////////////////////////
291
        // as_feature_list
292
        template<typename Features, typename Weight>
293
        struct as_feature_list
294
          : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >
295
        {
296
        };
297

    
298
        template<typename Features>
299
        struct as_feature_list<Features, void>
300
          : mpl::transform_view<Features, as_feature<mpl::_1> >
301
        {
302
        };
303

    
304
        ///////////////////////////////////////////////////////////////////////////
305
        // accumulator_wrapper
306
        template<typename Accumulator, typename Feature>
307
        struct accumulator_wrapper
308
          : Accumulator
309
        {
310
            typedef Feature feature_tag;
311

    
312
            accumulator_wrapper(accumulator_wrapper const &that)
313
              : Accumulator(*static_cast<Accumulator const *>(&that))
314
            {
315
            }
316

    
317
            template<typename Args>
318
            accumulator_wrapper(Args const &args)
319
              : Accumulator(args)
320
            {
321
            }
322
        };
323

    
324
        ///////////////////////////////////////////////////////////////////////////
325
        // to_accumulator
326
        template<typename Feature, typename Sample, typename Weight>
327
        struct to_accumulator
328
        {
329
            typedef
330
                accumulator_wrapper<
331
                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
332
                  , Feature
333
                >
334
            type;
335
        };
336

    
337
        template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>
338
        struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >
339
        {
340
            BOOST_MPL_ASSERT((is_same<Tag, void>));
341
            BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));
342

    
343
            typedef
344
                accumulator_wrapper<
345
                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
346
                  , Feature
347
                >
348
            accumulator_type;
349

    
350
            typedef
351
                typename mpl::if_<
352
                    typename Feature::is_weight_accumulator
353
                  , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>
354
                  , accumulator_type
355
                >::type
356
            type;
357
        };
358

    
359
        // BUGBUG work around an MPL bug wrt map insertion
360
        template<typename FeatureMap, typename Feature>
361
        struct insert_feature
362
          : mpl::eval_if<
363
                mpl::has_key<FeatureMap, typename feature_of<Feature>::type>
364
              , mpl::identity<FeatureMap>
365
              , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >
366
            >
367
        {
368
        };
369

    
370
        template<typename FeatureMap, typename Feature, typename Weight>
371
        struct insert_dependencies
372
          : mpl::fold<
373
                as_feature_list<typename Feature::dependencies, Weight>
374
              , FeatureMap
375
              , insert_dependencies<
376
                    insert_feature<mpl::_1, mpl::_2>
377
                  , mpl::_2
378
                  , Weight
379
                >
380
            >
381
        {
382
        };
383

    
384
        template<typename FeatureMap, typename Features, typename Weight>
385
        struct insert_sequence
386
          : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps
387
                as_feature_list<Features, Weight>
388
              , FeatureMap
389
              , insert_feature<mpl::_1, mpl::_2>
390
            >
391
        {
392
        };
393

    
394
        template<typename Features, typename Sample, typename Weight>
395
        struct make_accumulator_tuple
396
        {
397
            typedef
398
                typename mpl::fold<
399
                    as_feature_list<Features, Weight>
400
                  , mpl::map0<>
401
                  , mpl::if_<
402
                        mpl::is_sequence<mpl::_2>
403
                      , insert_sequence<mpl::_1, mpl::_2, Weight>
404
                      , insert_feature<mpl::_1, mpl::_2>
405
                    >
406
                >::type
407
            feature_map;
408

    
409
            // for each element in the map, add its dependencies also
410
            typedef
411
                typename mpl::fold<
412
                    feature_map
413
                  , feature_map
414
                  , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>
415
                >::type
416
            feature_map_with_dependencies;
417

    
418
            // turn the map into a vector so we can sort it
419
            typedef
420
                typename mpl::insert_range<
421
                    mpl::vector<>
422
                  , mpl::end<mpl::vector<> >::type
423
                  , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >
424
                >::type
425
            feature_vector_with_dependencies;
426

    
427
            // sort the features according to which is derived from which
428
            typedef
429
                typename mpl::sort<
430
                    feature_vector_with_dependencies
431
                  , is_dependent_on<mpl::_2, mpl::_1>
432
                >::type
433
            sorted_feature_vector;
434

    
435
            // From the vector of features, construct a vector of accumulators
436
            typedef
437
                typename mpl::transform<
438
                    sorted_feature_vector
439
                  , to_accumulator<mpl::_1, Sample, Weight>
440
                >::type
441
            type;
442
        };
443

    
444
    } // namespace detail
445

    
446
}} // namespace boost::accumulators
447

    
448
#endif