PageRenderTime 53ms CodeModel.GetById 16ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://hadesmem.googlecode.com/
C++ Header | 411 lines | 330 code | 45 blank | 36 comment | 0 complexity | 6c9d75ae93bacccd44550c1c8ef52d06 MD5 | raw file
  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/fold.hpp>
 15#include <boost/mpl/size.hpp>
 16#include <boost/mpl/sort.hpp>
 17#include <boost/mpl/insert.hpp>
 18#include <boost/mpl/assert.hpp>
 19#include <boost/mpl/remove.hpp>
 20#include <boost/mpl/vector.hpp>
 21#include <boost/mpl/inherit.hpp>
 22#include <boost/mpl/identity.hpp>
 23#include <boost/mpl/equal_to.hpp>
 24#include <boost/mpl/contains.hpp>
 25#include <boost/mpl/transform.hpp>
 26#include <boost/mpl/is_sequence.hpp>
 27#include <boost/mpl/placeholders.hpp>
 28#include <boost/mpl/insert_range.hpp>
 29#include <boost/mpl/transform_view.hpp>
 30#include <boost/mpl/inherit_linearly.hpp>
 31#include <boost/type_traits/is_base_and_derived.hpp>
 32#include <boost/preprocessor/repetition/repeat.hpp>
 33#include <boost/preprocessor/repetition/enum_params.hpp>
 34#include <boost/preprocessor/facilities/intercept.hpp>
 35#include <boost/accumulators/accumulators_fwd.hpp>
 36#include <boost/fusion/include/next.hpp>
 37#include <boost/fusion/include/equal_to.hpp>
 38#include <boost/fusion/include/value_of.hpp>
 39#include <boost/fusion/include/mpl.hpp>
 40#include <boost/fusion/include/end.hpp>
 41#include <boost/fusion/include/begin.hpp>
 42#include <boost/fusion/include/cons.hpp>
 43
 44namespace boost { namespace accumulators
 45{
 46    ///////////////////////////////////////////////////////////////////////////
 47    // as_feature
 48    template<typename Feature>
 49    struct as_feature
 50    {
 51        typedef Feature type;
 52    };
 53
 54    ///////////////////////////////////////////////////////////////////////////
 55    // weighted_feature
 56    template<typename Feature>
 57    struct as_weighted_feature
 58    {
 59        typedef Feature type;
 60    };
 61
 62    ///////////////////////////////////////////////////////////////////////////
 63    // feature_of
 64    template<typename Feature>
 65    struct feature_of
 66    {
 67        typedef Feature type;
 68    };
 69
 70    namespace detail
 71    {
 72        ///////////////////////////////////////////////////////////////////////////
 73        // feature_tag
 74        template<typename Accumulator>
 75        struct feature_tag
 76        {
 77            typedef typename Accumulator::feature_tag type;
 78        };
 79
 80        template<typename Feature>
 81        struct undroppable
 82        {
 83            typedef Feature type;
 84        };
 85
 86        template<typename Feature>
 87        struct undroppable<tag::droppable<Feature> >
 88        {
 89            typedef Feature type;
 90        };
 91
 92        // For the purpose of determining whether one feature depends on another,
 93        // disregard whether the feature is droppable or not.
 94        template<typename A, typename B>
 95        struct is_dependent_on
 96          : is_base_and_derived<
 97                typename undroppable<B>::type
 98              , typename undroppable<A>::type
 99            >
100        {};
101
102        template<typename Features>
103        struct depends_on_base
104          : mpl::inherit_linearly<
105                typename mpl::sort<Features, is_dependent_on<mpl::_1, mpl::_2> >::type
106                // Don't inherit multiply from a feature
107              , mpl::if_<
108                    is_dependent_on<mpl::_1, mpl::_2>
109                  , mpl::_1
110                  , mpl::inherit<mpl::_1, mpl::_2>
111                >
112            >::type
113        {
114        };
115    }
116
117    ///////////////////////////////////////////////////////////////////////////
118    /// depends_on
119    template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
120    struct depends_on
121      : detail::depends_on_base<
122            typename mpl::transform<
123                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
124              , as_feature<mpl::_1>
125            >::type
126        >
127    {
128        typedef mpl::false_ is_weight_accumulator;
129        typedef
130            typename mpl::transform<
131                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
132              , as_feature<mpl::_1>
133            >::type
134        dependencies;
135    };
136
137    namespace detail
138    {
139        template<typename Feature>
140        struct matches_feature
141        {
142            template<typename Accumulator>
143            struct apply
144              : is_same<
145                    typename feature_of<typename as_feature<Feature>::type>::type
146                  , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type
147                >
148            {};
149        };
150
151        template<typename Features, typename Accumulator>
152        struct contains_feature_of
153        {
154            typedef
155                mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >
156            features_list;
157
158            typedef
159                typename feature_of<typename feature_tag<Accumulator>::type>::type
160            the_feature;
161
162            typedef
163                typename mpl::contains<features_list, the_feature>::type
164            type;
165        };
166
167        // This is to work around a bug in early versions of Fusion which caused
168        // a compile error if contains_feature_of<List, mpl::_> is used as a
169        // predicate to fusion::find_if
170        template<typename Features>
171        struct contains_feature_of_
172        {
173            template<typename Accumulator>
174            struct apply
175              : contains_feature_of<Features, Accumulator>
176            {};
177        };
178
179        template<
180            typename First
181          , typename Last
182          , bool is_empty = fusion::result_of::equal_to<First, Last>::value
183        >
184        struct build_acc_list;
185
186        template<typename First, typename Last>
187        struct build_acc_list<First, Last, true>
188        {
189            typedef fusion::nil type;
190
191            template<typename Args>
192            static fusion::nil
193            call(Args const &, First const&, Last const&)
194            {
195                return fusion::nil();
196            }
197        };
198
199        template<typename First, typename Last>
200        struct build_acc_list<First, Last, false>
201        {
202            typedef
203                build_acc_list<typename fusion::result_of::next<First>::type, Last>
204            next_build_acc_list;
205
206            typedef fusion::cons<
207                typename fusion::result_of::value_of<First>::type
208              , typename next_build_acc_list::type>
209            type;
210
211            template<typename Args>
212            static type
213            call(Args const &args, First const& f, Last const& l)
214            {
215                return type(args, next_build_acc_list::call(args, fusion::next(f), l));
216            }
217        };
218
219        namespace meta
220        {
221            template<typename Sequence>
222            struct make_acc_list
223              : build_acc_list<
224                    typename fusion::result_of::begin<Sequence>::type
225                  , typename fusion::result_of::end<Sequence>::type
226                >
227            {};
228        }
229
230        template<typename Sequence, typename Args>
231        typename meta::make_acc_list<Sequence>::type
232        make_acc_list(Sequence const &seq, Args const &args)
233        {
234            return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
235        }
236
237        ///////////////////////////////////////////////////////////////////////////
238        // checked_as_weighted_feature
239        template<typename Feature>
240        struct checked_as_weighted_feature
241        {
242            typedef typename as_feature<Feature>::type feature_type;
243            typedef typename as_weighted_feature<feature_type>::type type;
244            // weighted and non-weighted flavors should provide the same feature.
245            BOOST_MPL_ASSERT((
246                is_same<
247                    typename feature_of<feature_type>::type
248                  , typename feature_of<type>::type
249                >
250            ));
251        };
252
253        ///////////////////////////////////////////////////////////////////////////
254        // as_feature_list
255        template<typename Features, typename Weight>
256        struct as_feature_list
257          : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >
258        {
259        };
260
261        template<typename Features>
262        struct as_feature_list<Features, void>
263          : mpl::transform_view<Features, as_feature<mpl::_1> >
264        {
265        };
266
267        ///////////////////////////////////////////////////////////////////////////
268        // accumulator_wrapper
269        template<typename Accumulator, typename Feature>
270        struct accumulator_wrapper
271          : Accumulator
272        {
273            typedef Feature feature_tag;
274
275            accumulator_wrapper(accumulator_wrapper const &that)
276              : Accumulator(*static_cast<Accumulator const *>(&that))
277            {
278            }
279
280            template<typename Args>
281            accumulator_wrapper(Args const &args)
282              : Accumulator(args)
283            {
284            }
285        };
286
287        ///////////////////////////////////////////////////////////////////////////
288        // to_accumulator
289        template<typename Feature, typename Sample, typename Weight>
290        struct to_accumulator
291        {
292            typedef
293                accumulator_wrapper<
294                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
295                  , Feature
296                >
297            type;
298        };
299
300        template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>
301        struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >
302        {
303            BOOST_MPL_ASSERT((is_same<Tag, void>));
304            BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));
305
306            typedef
307                accumulator_wrapper<
308                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
309                  , Feature
310                >
311            accumulator_type;
312
313            typedef
314                typename mpl::if_<
315                    typename Feature::is_weight_accumulator
316                  , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>
317                  , accumulator_type
318                >::type
319            type;
320        };
321
322        // BUGBUG work around a MPL bug wrt map insertion
323        template<typename FeatureMap, typename Feature>
324        struct insert_feature
325          : mpl::eval_if<
326                mpl::has_key<FeatureMap, typename feature_of<Feature>::type>
327              , mpl::identity<FeatureMap>
328              , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >
329            >
330        {
331        };
332
333        template<typename FeatureMap, typename Feature, typename Weight>
334        struct insert_dependencies
335          : mpl::fold<
336                as_feature_list<typename Feature::dependencies, Weight>
337              , FeatureMap
338              , insert_dependencies<
339                    insert_feature<mpl::_1, mpl::_2>
340                  , mpl::_2
341                  , Weight
342                >
343            >
344        {
345        };
346
347        template<typename FeatureMap, typename Features, typename Weight>
348        struct insert_sequence
349          : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps
350                as_feature_list<Features, Weight>
351              , FeatureMap
352              , insert_feature<mpl::_1, mpl::_2>
353            >
354        {
355        };
356
357        template<typename Features, typename Sample, typename Weight>
358        struct make_accumulator_tuple
359        {
360            typedef
361                typename mpl::fold<
362                    as_feature_list<Features, Weight>
363                  , mpl::map0<>
364                  , mpl::if_<
365                        mpl::is_sequence<mpl::_2>
366                      , insert_sequence<mpl::_1, mpl::_2, Weight>
367                      , insert_feature<mpl::_1, mpl::_2>
368                    >
369                >::type
370            feature_map;
371
372            // for each element in the map, add its dependencies also
373            typedef
374                typename mpl::fold<
375                    feature_map
376                  , feature_map
377                  , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>
378                >::type
379            feature_map_with_dependencies;
380
381            // turn the map into a vector so we can sort it
382            typedef
383                typename mpl::insert_range<
384                    mpl::vector<>
385                  , mpl::end<mpl::vector<> >::type
386                  , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >
387                >::type
388            feature_vector_with_dependencies;
389
390            // sort the features according to which is derived from which
391            typedef
392                typename mpl::sort<
393                    feature_vector_with_dependencies
394                  , is_dependent_on<mpl::_2, mpl::_1>
395                >::type
396            sorted_feature_vector;
397
398            // From the vector of features, construct a vector of accumulators
399            typedef
400                typename mpl::transform<
401                    sorted_feature_vector
402                  , to_accumulator<mpl::_1, Sample, Weight>
403                >::type
404            type;
405        };
406
407    } // namespace detail
408
409}} // namespace boost::accumulators
410
411#endif