00001 #ifndef _theplu_yat_utility_iterator_traits_
00002 #define _theplu_yat_utility_iterator_traits_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "DataWeight.h"
00028
00029 #include <boost/mpl/logical.hpp>
00030 #include <boost/type_traits/is_const.hpp>
00031 #include <boost/type_traits/is_convertible.hpp>
00032 #include <boost/type_traits/is_same.hpp>
00033 #include <boost/type_traits/remove_reference.hpp>
00034 #include <boost/utility/enable_if.hpp>
00035
00036 #include <iterator>
00037
00038 namespace theplu {
00039 namespace yat {
00040 namespace utility {
00041
00046 struct unweighted_iterator_tag {};
00047
00054 struct weighted_iterator_tag {};
00055
00056
00057 namespace detail {
00063 template <typename T, typename Enable = void>
00064 struct weighted_iterator_traits_detail {
00068 typedef unweighted_iterator_tag type;
00069 };
00070
00076 template <typename T>
00077 struct weighted_iterator_traits_detail<T, typename boost::enable_if<typename boost::is_convertible<T, DataWeight> >::type > {
00081 typedef weighted_iterator_tag type;
00082 };
00083
00084 }
00085
00086
00094 template <class Iterator>
00095 struct weighted_iterator_traits
00096 {
00097 private:
00098 typedef typename std::iterator_traits<Iterator>::value_type value;
00099 public:
00104 typedef typename detail::weighted_iterator_traits_detail<value>::type type;
00105 };
00106
00107
00108 namespace detail {
00116 template <class T1, class T2>
00117 struct unweighted_type_and {
00121 typedef weighted_iterator_tag type;
00122 };
00123
00130 template <>
00131 struct unweighted_type_and<unweighted_iterator_tag, unweighted_iterator_tag> {
00135 typedef unweighted_iterator_tag type;
00136 };
00137 }
00138
00144 template <class T1, class T2>
00145 struct weighted_if_any2 {
00146 private:
00147 typedef typename weighted_iterator_traits<T1>::type w_type1;
00148 typedef typename weighted_iterator_traits<T2>::type w_type2;
00149 public:
00151 typedef typename detail::unweighted_type_and<w_type1, w_type2>::type type;
00152 };
00153
00157 template <class T1, class T2, class T3>
00158 struct weighted_if_any3 {
00159 private:
00160 typedef typename weighted_if_any2<T1, T2>::type tmp;
00161 typedef typename weighted_iterator_traits<T3>::type w_type3;
00162 public:
00164 typedef typename detail::unweighted_type_and<tmp, w_type3>::type type;
00165 };
00166
00167 namespace detail {
00173 inline void
00174 check_iterator_is_unweighted(utility::unweighted_iterator_tag x){}
00175 }
00176
00182 template <class Iter>
00183 void check_iterator_is_unweighted(Iter iter)
00184 { detail::check_iterator_is_unweighted(typename
00185 weighted_iterator_traits<Iter>::type());
00186 }
00187
00188
00189 namespace detail {
00190
00200 typedef char yes;
00207 typedef char (&no)[2];
00216 yes has_mutable(double&);
00224 template<typename T>
00225 no has_mutable(const T&);
00226
00234 template <class Iter>
00235 struct iter_has_mutable_data
00236 {
00238 static Iter iter;
00240 static const bool value =
00241 sizeof(has_mutable((*iter).data())) == sizeof(yes);
00242 };
00243
00244
00252 template <class Iter>
00253 struct iter_has_mutable_weight
00254 {
00256 static Iter iter;
00258 static const bool value =
00259 sizeof(has_mutable((*iter).weight())) == sizeof(yes);
00260 };
00261
00262
00274 template<typename Iter>
00275 struct is_weighted
00276 : public boost::is_same<weighted_iterator_tag
00277 , typename weighted_iterator_traits<Iter>::type>
00278 {};
00279
00285 template<typename Iter>
00286 struct is_unweighted
00287 : public boost::is_same<unweighted_iterator_tag
00288 , typename weighted_iterator_traits<Iter>::type>
00289 {};
00290
00291
00299 template <typename Iter, typename Enable = void>
00300 struct iterator_traits_detail {
00304 typedef typename std::iterator_traits<Iter>::reference data_reference;
00305
00309 typedef const double weight_reference;
00310
00314 data_reference data(Iter iter) const { return *iter; }
00315
00319 weight_reference weight(Iter iter) const { return 1.0; }
00320 };
00321
00326 template<bool>
00327 struct mutable_reference {
00329 typedef const double type;
00330 };
00331
00336 template<>
00337 struct mutable_reference<true> {
00339 typedef double& type;
00340 };
00341
00342
00348
00349 template <typename Iter>
00350 struct iterator_traits_detail<Iter,
00351 typename boost::enable_if<is_weighted<Iter> >::type >
00352 {
00357 typedef
00358 typename mutable_reference<iter_has_mutable_data<Iter>::value>::type
00359 data_reference;
00360
00365 typedef
00366 typename mutable_reference<iter_has_mutable_weight<Iter>::value>::type
00367 weight_reference;
00368
00372 data_reference data(Iter iter) const { return (*iter).data(); }
00373
00377 weight_reference weight(Iter iter) const { return (*iter).weight(); }
00378 };
00379
00380 }
00381
00390 template <typename Iter>
00391 struct iterator_traits {
00392 private:
00393 typedef detail::iterator_traits_detail<Iter> traits;
00394 public:
00404 typedef typename traits::data_reference data_reference;
00405
00414 typedef typename traits::weight_reference weight_reference;
00415
00419 data_reference data(Iter iter) const
00420 { return traits().data(iter); }
00421
00425 weight_reference weight(Iter iter) const
00426 { return traits().weight(iter); }
00427
00428 };
00429
00430 }}}
00431
00432 #endif