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 #include "DataWeight.h"
00027
00028 #include <iterator>
00029
00030 namespace theplu {
00031 namespace yat {
00032 namespace utility {
00033
00038 struct unweighted_iterator_tag {};
00039
00046 struct weighted_iterator_tag {};
00047
00048
00049 namespace detail {
00055 template <typename T>
00056 struct weighted_iterator_traits_detail {
00060 typedef unweighted_iterator_tag type;
00061 };
00062
00068 template <>
00069 struct weighted_iterator_traits_detail<DataWeight> {
00073 typedef weighted_iterator_tag type;
00074 };
00075 }
00076
00077
00084 template <class T>
00085 struct weighted_iterator_traits
00086 {
00087 private:
00088 typedef typename std::iterator_traits<T>::value_type value;
00089 public:
00093 typedef typename detail::weighted_iterator_traits_detail<value>::type type;
00094 };
00095
00096
00097 namespace detail {
00105 template <class T1, class T2>
00106 struct unweighted_type_and {
00110 typedef weighted_iterator_tag type;
00111 };
00112
00119 template <>
00120 struct unweighted_type_and<unweighted_iterator_tag, unweighted_iterator_tag> {
00124 typedef unweighted_iterator_tag type;
00125 };
00126 }
00127
00133 template <class T1, class T2>
00134 struct weighted_if_any2 {
00135 private:
00136 typedef typename weighted_iterator_traits<T1>::type w_type1;
00137 typedef typename weighted_iterator_traits<T2>::type w_type2;
00138 public:
00140 typedef typename detail::unweighted_type_and<w_type1, w_type2>::type type;
00141 };
00142
00146 template <class T1, class T2, class T3>
00147 struct weighted_if_any3 {
00148 private:
00149 typedef typename weighted_if_any2<T1, T2>::type tmp;
00150 typedef typename weighted_iterator_traits<T3>::type w_type3;
00151 public:
00153 typedef typename detail::unweighted_type_and<tmp, w_type3>::type type;
00154 };
00155
00156 namespace detail {
00158 inline void
00159 check_iterator_is_unweighted(utility::unweighted_iterator_tag x){}
00160 }
00161
00167 template <class Iter>
00168 void check_iterator_is_unweighted(Iter iter)
00169 { detail::check_iterator_is_unweighted(typename
00170 weighted_iterator_traits<Iter>::type());
00171 }
00172
00173
00174 namespace detail {
00183 template <typename Iter, typename T >
00184 struct iterator_traits_detail
00185 {
00189 typedef typename std::iterator_traits<Iter>::reference data_reference;
00190
00194 typedef double weight_reference;
00195
00199 iterator_traits_detail(void)
00200 { check_iterator_is_unweighted(typename
00201 weighted_iterator_traits<Iter>::type());
00202 }
00203
00207 data_reference data(Iter iter) const { return *iter; }
00208
00212 weight_reference weight(Iter iter) const { return 1.0; }
00213 };
00214
00215
00219 template <typename Iter>
00220 struct iterator_traits_detail<Iter, DataWeight&> {
00224 typedef double& data_reference;
00225
00229 typedef double& weight_reference;
00230
00234 data_reference data(Iter iter) const { return iter->data(); }
00235
00239 weight_reference weight(Iter iter) const { return iter->weight(); }
00240 };
00241
00242
00246 template <typename Iter>
00247 struct iterator_traits_detail<Iter, const DataWeight&> {
00251 typedef const double& data_reference;
00252
00256 typedef const double& weight_reference;
00257
00261 data_reference data(Iter iter) const { return iter->data(); }
00262
00266 weight_reference weight(Iter iter) const { return iter->weight(); }
00267 };
00268
00269
00273 template <typename Iter>
00274 struct iterator_traits_detail<Iter, const DataWeight> {
00278 typedef const double data_reference;
00279
00283 typedef const double weight_reference;
00284
00288 data_reference data(Iter iter) const { return (*iter).data(); }
00289
00293 weight_reference weight(Iter iter) const { return (*iter).weight(); }
00294 };
00295 }
00296
00313 template <typename Iter>
00314 struct iterator_traits {
00315 private:
00316 typedef typename std::iterator_traits<Iter>::reference reference;
00317 typedef detail::iterator_traits_detail<Iter, reference> traits;
00318 public:
00323 typedef typename traits::data_reference data_reference;
00324
00329 typedef typename traits::weight_reference weight_reference;
00330
00334 data_reference data(Iter iter) const
00335 { return traits().data(iter); }
00336
00340 weight_reference weight(Iter iter) const
00341 { return traits().weight(iter); }
00342
00343 };
00344
00345
00346 }}}
00347
00348 #endif