annotate DEPENDENCIES/generic/include/boost/accumulators/framework/depends_on.hpp @ 133:4acb5d8d80b6 tip

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