yat/utility/iterator_traits.h

Code
Comments
Other
Rev Date Author Line
908 28 Sep 07 peter 1 #ifndef _theplu_yat_utility_iterator_traits_
908 28 Sep 07 peter 2 #define _theplu_yat_utility_iterator_traits_
908 28 Sep 07 peter 3
908 28 Sep 07 peter 4 // $Id$
908 28 Sep 07 peter 5
908 28 Sep 07 peter 6 /*
4359 23 Aug 23 peter 7   Copyright (C) 2007 Peter Johansson
2119 12 Dec 09 peter 8   Copyright (C) 2008 Jari Häkkinen, Peter Johansson, Markus Ringnér
4359 23 Aug 23 peter 9   Copyright (C) 2010, 2011, 2014 Peter Johansson
908 28 Sep 07 peter 10
1437 25 Aug 08 peter 11   This file is part of the yat library, http://dev.thep.lu.se/yat
908 28 Sep 07 peter 12
908 28 Sep 07 peter 13   The yat library is free software; you can redistribute it and/or
908 28 Sep 07 peter 14   modify it under the terms of the GNU General Public License as
1486 09 Sep 08 jari 15   published by the Free Software Foundation; either version 3 of the
908 28 Sep 07 peter 16   License, or (at your option) any later version.
908 28 Sep 07 peter 17
908 28 Sep 07 peter 18   The yat library is distributed in the hope that it will be useful,
908 28 Sep 07 peter 19   but WITHOUT ANY WARRANTY; without even the implied warranty of
908 28 Sep 07 peter 20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
908 28 Sep 07 peter 21   General Public License for more details.
908 28 Sep 07 peter 22
908 28 Sep 07 peter 23   You should have received a copy of the GNU General Public License
1487 10 Sep 08 jari 24   along with yat. If not, see <http://www.gnu.org/licenses/>.
908 28 Sep 07 peter 25 */
908 28 Sep 07 peter 26
1382 17 Jul 08 peter 27 #include "DataWeight.h"
1382 17 Jul 08 peter 28
3322 06 Oct 14 peter 29 #include <boost/iterator/iterator_traits.hpp>
2202 21 Feb 10 peter 30 #include <boost/mpl/logical.hpp>
2202 21 Feb 10 peter 31 #include <boost/type_traits/is_const.hpp>
2159 19 Jan 10 peter 32 #include <boost/type_traits/is_convertible.hpp>
2202 21 Feb 10 peter 33 #include <boost/type_traits/is_same.hpp>
2202 21 Feb 10 peter 34 #include <boost/type_traits/remove_reference.hpp>
2159 19 Jan 10 peter 35 #include <boost/utility/enable_if.hpp>
2159 19 Jan 10 peter 36
1373 16 Jul 08 peter 37 #include <iterator>
1373 16 Jul 08 peter 38
908 28 Sep 07 peter 39 namespace theplu {
908 28 Sep 07 peter 40 namespace yat {
908 28 Sep 07 peter 41 namespace utility {
908 28 Sep 07 peter 42
966 11 Oct 07 peter 43   /**
908 28 Sep 07 peter 44     Struct to be used to make compile-time decision that Iterator is
908 28 Sep 07 peter 45     unweighted, which is the default.
3501 31 May 16 peter 46    */
1092 14 Feb 08 peter 47   struct unweighted_iterator_tag {};
3501 31 May 16 peter 48
966 11 Oct 07 peter 49   /**
908 28 Sep 07 peter 50     Struct to be used to make compile-time decision that Iterator is
1115 21 Feb 08 markus 51     weighted. Some algorithms come also in a weighted version and
908 28 Sep 07 peter 52     this tag could be used to decide on using them (rather than
1115 21 Feb 08 markus 53     the corresponding unweighted algorithm).
3501 31 May 16 peter 54    */
1092 14 Feb 08 peter 55   struct weighted_iterator_tag {};
908 28 Sep 07 peter 56
1089 14 Feb 08 peter 57
3188 25 Mar 14 peter 58 /// \cond IGNORE_DOXYGEN
3188 25 Mar 14 peter 59
1591 17 Oct 08 peter 60 namespace detail {
1541 30 Sep 08 peter 61   /**
1541 30 Sep 08 peter 62      \internal
1541 30 Sep 08 peter 63
1541 30 Sep 08 peter 64      used in weighted_iterator_traits
1089 14 Feb 08 peter 65   */
2159 19 Jan 10 peter 66   template <typename T, typename Enable = void>
1541 30 Sep 08 peter 67   struct weighted_iterator_traits_detail {
1541 30 Sep 08 peter 68     /**
1541 30 Sep 08 peter 69        default is a iterator unweighted
1541 30 Sep 08 peter 70     */
1092 14 Feb 08 peter 71     typedef unweighted_iterator_tag type;
3322 06 Oct 14 peter 72   };
908 28 Sep 07 peter 73
3322 06 Oct 14 peter 74   /**
1541 30 Sep 08 peter 75       \internal
1541 30 Sep 08 peter 76
2202 21 Feb 10 peter 77       specialization for iterators with value type convertible to DataWeight
1541 30 Sep 08 peter 78   */
2159 19 Jan 10 peter 79   template <typename T>
2202 21 Feb 10 peter 80   struct weighted_iterator_traits_detail<T, typename boost::enable_if<typename boost::is_convertible<T, DataWeight> >::type > {
1382 17 Jul 08 peter 81     /**
2202 21 Feb 10 peter 82        Iterators with value type convertible to DataWeight is weighted
1541 30 Sep 08 peter 83      */
1382 17 Jul 08 peter 84     typedef weighted_iterator_tag type;
3322 06 Oct 14 peter 85   };
2159 19 Jan 10 peter 86
1591 17 Oct 08 peter 87 } // namespace detail
1382 17 Jul 08 peter 88
3188 25 Mar 14 peter 89 /// \endcond
1591 17 Oct 08 peter 90
3188 25 Mar 14 peter 91
3322 06 Oct 14 peter 92   /**
2202 21 Feb 10 peter 93       Metafunction to decide whether an Iterator is weighted or
2202 21 Feb 10 peter 94       non-weighted. This (default) implementation returns
3322 06 Oct 14 peter 95       unweighted_iterator_tag, unless \c value_type of Iterator is
2202 21 Feb 10 peter 96       convertible to DataWeight in which case weighted_iterator_tag is
2202 21 Feb 10 peter 97       returned.
3322 06 Oct 14 peter 98
3322 06 Oct 14 peter 99       Type Requirements:
3322 06 Oct 14 peter 100       - \c boost::iterator_value<Iterator>::type must be defined, which is
3322 06 Oct 14 peter 101       guaranteed if \c Iterator is a \readable_iterator
3322 06 Oct 14 peter 102       (\c std::ostream_iterator e.g. does not work)
1541 30 Sep 08 peter 103   */
2202 21 Feb 10 peter 104   template <class Iterator>
3322 06 Oct 14 peter 105   struct weighted_iterator_traits
1541 30 Sep 08 peter 106   {
1541 30 Sep 08 peter 107   private:
3322 06 Oct 14 peter 108     typedef typename boost::iterator_value<Iterator>::type value;
1541 30 Sep 08 peter 109   public:
1382 17 Jul 08 peter 110     /**
2202 21 Feb 10 peter 111        \return weighted_iterator_tag if Iterator::value_type is
2202 21 Feb 10 peter 112        convertible to DataWeight
1541 30 Sep 08 peter 113      */
1591 17 Oct 08 peter 114     typedef typename detail::weighted_iterator_traits_detail<value>::type type;
1382 17 Jul 08 peter 115   };
1382 17 Jul 08 peter 116
1382 17 Jul 08 peter 117
3188 25 Mar 14 peter 118 /// \cond IGNORE_DOXYGEN
1591 17 Oct 08 peter 119 namespace detail {
1382 17 Jul 08 peter 120   /**
1150 25 Feb 08 peter 121      \internal
1150 25 Feb 08 peter 122
958 10 Oct 07 peter 123     Metafunction that works on a pair weighted-unweighted types and
958 10 Oct 07 peter 124     return weighted_type. The metafunction is specialized for
958 10 Oct 07 peter 125     unweighted unweighted in which case unweighted is returned.
958 10 Oct 07 peter 126    */
916 30 Sep 07 peter 127   template <class T1, class T2>
958 10 Oct 07 peter 128   struct unweighted_type_and {
1125 22 Feb 08 peter 129     /**
1125 22 Feb 08 peter 130        default return weighted_iterator_tag
1125 22 Feb 08 peter 131      */
1092 14 Feb 08 peter 132     typedef weighted_iterator_tag type;
916 30 Sep 07 peter 133   };
916 30 Sep 07 peter 134
966 11 Oct 07 peter 135   /**
1150 25 Feb 08 peter 136      \internal
1150 25 Feb 08 peter 137
958 10 Oct 07 peter 138     Specialization that sets type to be unweighted when both arguments
958 10 Oct 07 peter 139     are unweighted
958 10 Oct 07 peter 140    */
958 10 Oct 07 peter 141   template <>
1092 14 Feb 08 peter 142   struct unweighted_type_and<unweighted_iterator_tag, unweighted_iterator_tag> {
1125 22 Feb 08 peter 143     /**
1125 22 Feb 08 peter 144        return unweighted_iterator_tag
1125 22 Feb 08 peter 145      */
1092 14 Feb 08 peter 146     typedef unweighted_iterator_tag type;
958 10 Oct 07 peter 147   };
1591 17 Oct 08 peter 148 } // namespace detail
958 10 Oct 07 peter 149
3188 25 Mar 14 peter 150 /// \endcond
3188 25 Mar 14 peter 151
3188 25 Mar 14 peter 152
966 11 Oct 07 peter 153   /**
958 10 Oct 07 peter 154     struct used to determine if a pair of iterators should be treated
958 10 Oct 07 peter 155     as weighted. If both iterators are unweighted, type is set to
958 10 Oct 07 peter 156     unweighted else weighted.
958 10 Oct 07 peter 157   */
916 30 Sep 07 peter 158   template <class T1, class T2>
958 10 Oct 07 peter 159   struct weighted_if_any2 {
1125 22 Feb 08 peter 160   private:
958 10 Oct 07 peter 161     typedef typename weighted_iterator_traits<T1>::type w_type1;
958 10 Oct 07 peter 162     typedef typename weighted_iterator_traits<T2>::type w_type2;
1125 22 Feb 08 peter 163   public:
1125 22 Feb 08 peter 164     /// return unweighted if both are unweighted
1591 17 Oct 08 peter 165     typedef typename detail::unweighted_type_and<w_type1, w_type2>::type type;
916 30 Sep 07 peter 166   };
916 30 Sep 07 peter 167
966 11 Oct 07 peter 168   /**
958 10 Oct 07 peter 169     Same as weighted_iterator_traits2 but for 3 arguments.
958 10 Oct 07 peter 170    */
958 10 Oct 07 peter 171   template <class T1, class T2, class T3>
958 10 Oct 07 peter 172   struct weighted_if_any3 {
1125 22 Feb 08 peter 173   private:
958 10 Oct 07 peter 174     typedef typename weighted_if_any2<T1, T2>::type tmp;
958 10 Oct 07 peter 175     typedef typename weighted_iterator_traits<T3>::type w_type3;
1125 22 Feb 08 peter 176   public:
1125 22 Feb 08 peter 177     /// return unweighted if all are unweighted
1591 17 Oct 08 peter 178     typedef typename detail::unweighted_type_and<tmp, w_type3>::type type;
958 10 Oct 07 peter 179   };
958 10 Oct 07 peter 180
3188 25 Mar 14 peter 181   /// \cond IGNORE_DOXYGEN
1591 17 Oct 08 peter 182   namespace detail {
3501 31 May 16 peter 183     /**
2202 21 Feb 10 peter 184         \internal
2202 21 Feb 10 peter 185
3501 31 May 16 peter 186         check (at compile time) that iterator is unweighted.
2202 21 Feb 10 peter 187     */
3501 31 May 16 peter 188     inline void
3501 31 May 16 peter 189     check_iterator_is_unweighted(utility::unweighted_iterator_tag x){}
1591 17 Oct 08 peter 190   } // namespace detail
966 11 Oct 07 peter 191
3188 25 Mar 14 peter 192   /// \endcond
3188 25 Mar 14 peter 193
966 11 Oct 07 peter 194   /**
1591 17 Oct 08 peter 195      \brief check (at compile time) that iterator is unweighted.
1591 17 Oct 08 peter 196
1591 17 Oct 08 peter 197      This function only compiles if iterator \a iter is unweighted.
966 11 Oct 07 peter 198    */
914 29 Sep 07 peter 199   template <class Iter>
3501 31 May 16 peter 200   void check_iterator_is_unweighted(Iter iter)
3501 31 May 16 peter 201   { detail::check_iterator_is_unweighted(typename
916 30 Sep 07 peter 202                                  weighted_iterator_traits<Iter>::type());
916 30 Sep 07 peter 203   }
914 29 Sep 07 peter 204
914 29 Sep 07 peter 205
3188 25 Mar 14 peter 206 /// \cond IGNORE_DOXYGEN
1591 17 Oct 08 peter 207 namespace detail {
2202 21 Feb 10 peter 208
966 11 Oct 07 peter 209   /**
1541 30 Sep 08 peter 210      \internal
914 29 Sep 07 peter 211
2202 21 Feb 10 peter 212      The following block of code is used to detect if weighted
2202 21 Feb 10 peter 213      iterators have functions 'double& data(void)' or if they only
2202 21 Feb 10 peter 214      have the const version.
3501 31 May 16 peter 215
2202 21 Feb 10 peter 216      The technique used is taken from http://www.martinecker.com/wiki/
2202 21 Feb 10 peter 217    */
2202 21 Feb 10 peter 218   typedef char yes;
2202 21 Feb 10 peter 219   /**
2202 21 Feb 10 peter 220      \internal
914 29 Sep 07 peter 221
2202 21 Feb 10 peter 222      This type (no) and type yes have different sizes and are used to
2202 21 Feb 10 peter 223      differentiate between the two cases.
1541 30 Sep 08 peter 224    */
2202 21 Feb 10 peter 225   typedef char (&no)[2];
2202 21 Feb 10 peter 226   /**
2202 21 Feb 10 peter 227      \internal
1373 16 Jul 08 peter 228
2202 21 Feb 10 peter 229      Overloaded function with template below. If there exists a
2202 21 Feb 10 peter 230      function that returns double& that will used and otherwise
2202 21 Feb 10 peter 231      overloaded template below will be used. This implementation and
2202 21 Feb 10 peter 232      template return different types to differentiate the two cases.
2202 21 Feb 10 peter 233    */
2202 21 Feb 10 peter 234    yes has_mutable(double&);
2202 21 Feb 10 peter 235   /**
2202 21 Feb 10 peter 236      \internal
1373 16 Jul 08 peter 237
2202 21 Feb 10 peter 238      Function used in iter_has_mutable_data and
2202 21 Feb 10 peter 239      iter_has_mutable_weight. The default case is used if function
2202 21 Feb 10 peter 240      called (e.g. data() does not return double&.
2202 21 Feb 10 peter 241    */
2202 21 Feb 10 peter 242   template<typename T>
2202 21 Feb 10 peter 243   no has_mutable(const T&);
914 29 Sep 07 peter 244
2202 21 Feb 10 peter 245   /**
2202 21 Feb 10 peter 246      \internal
2202 21 Feb 10 peter 247
2202 21 Feb 10 peter 248      Struct to check if iterator has mutable data. *Iter must have a
2311 17 Aug 10 peter 249      function data(). If that function returns double& value is
2202 21 Feb 10 peter 250      true.
2202 21 Feb 10 peter 251    */
2202 21 Feb 10 peter 252   template <class Iter>
2202 21 Feb 10 peter 253   struct iter_has_mutable_data
2202 21 Feb 10 peter 254   {
2202 21 Feb 10 peter 255     /// instance of Iter
2202 21 Feb 10 peter 256     static Iter iter;
2202 21 Feb 10 peter 257     /// true if *iter has a function data() that returns double&
3501 31 May 16 peter 258     static const bool value =
2202 21 Feb 10 peter 259       sizeof(has_mutable((*iter).data())) == sizeof(yes);
1088 14 Feb 08 peter 260   };
914 29 Sep 07 peter 261
1382 17 Jul 08 peter 262
1382 17 Jul 08 peter 263   /**
2202 21 Feb 10 peter 264      \internal
2202 21 Feb 10 peter 265
2202 21 Feb 10 peter 266      Struct to check if iterator has mutable data. *Iter must have a
2311 17 Aug 10 peter 267      function data(). If that function returns double& value is
2202 21 Feb 10 peter 268      true.
1541 30 Sep 08 peter 269    */
2202 21 Feb 10 peter 270   template <class Iter>
2202 21 Feb 10 peter 271   struct iter_has_mutable_weight
2202 21 Feb 10 peter 272   {
2202 21 Feb 10 peter 273     /// instance of Iter
2202 21 Feb 10 peter 274     static Iter iter;
2202 21 Feb 10 peter 275     /// true if *iter has a function weight() that returns double&
3501 31 May 16 peter 276     static const bool value =
2202 21 Feb 10 peter 277       sizeof(has_mutable((*iter).weight())) == sizeof(yes);
2202 21 Feb 10 peter 278   };
1382 17 Jul 08 peter 279
1382 17 Jul 08 peter 280
2202 21 Feb 10 peter 281   /**
2202 21 Feb 10 peter 282      \internal
1382 17 Jul 08 peter 283
2202 21 Feb 10 peter 284      Convenience meta-function. The struct is-a boost::true_type if
2202 21 Feb 10 peter 285      Iter is a weighted iterator
1382 17 Jul 08 peter 286
2202 21 Feb 10 peter 287      The purpose of the struct is to be used in boost::mpl, for
2202 21 Feb 10 peter 288      example, in boost::mpl::and_.
1541 30 Sep 08 peter 289
2202 21 Feb 10 peter 290      \see weighted_iterator_traits
2202 21 Feb 10 peter 291    */
2202 21 Feb 10 peter 292   template<typename Iter>
3501 31 May 16 peter 293   struct is_weighted
2202 21 Feb 10 peter 294     : public boost::is_same<weighted_iterator_tag
3501 31 May 16 peter 295                             , typename weighted_iterator_traits<Iter>::type>
2202 21 Feb 10 peter 296   {};
2202 21 Feb 10 peter 297
1541 30 Sep 08 peter 298   /**
2202 21 Feb 10 peter 299      \internal
2202 21 Feb 10 peter 300
2202 21 Feb 10 peter 301      same is_weighted but negated
1541 30 Sep 08 peter 302    */
2202 21 Feb 10 peter 303   template<typename Iter>
3501 31 May 16 peter 304   struct is_unweighted
2202 21 Feb 10 peter 305     : public boost::is_same<unweighted_iterator_tag
3501 31 May 16 peter 306                             , typename weighted_iterator_traits<Iter>::type>
2202 21 Feb 10 peter 307   {};
2202 21 Feb 10 peter 308
2202 21 Feb 10 peter 309
2202 21 Feb 10 peter 310   /**
2202 21 Feb 10 peter 311      \internal
2202 21 Feb 10 peter 312
2202 21 Feb 10 peter 313      Default implementation of iterator_traits_detail. Is supposed to
2202 21 Feb 10 peter 314      be used for unweighted iterators. Weighted iterators use
2202 21 Feb 10 peter 315      specialization below.
2202 21 Feb 10 peter 316    */
2202 21 Feb 10 peter 317   template <typename Iter, typename Enable = void>
2202 21 Feb 10 peter 318   struct iterator_traits_detail {
1541 30 Sep 08 peter 319     /**
2202 21 Feb 10 peter 320        for unweighted data_reference is reference
1541 30 Sep 08 peter 321     */
2202 21 Feb 10 peter 322     typedef typename std::iterator_traits<Iter>::reference data_reference;
1541 30 Sep 08 peter 323
1541 30 Sep 08 peter 324     /**
2202 21 Feb 10 peter 325        for unweighted weight_reference is a double
1541 30 Sep 08 peter 326     */
2202 21 Feb 10 peter 327     typedef const double weight_reference;
1541 30 Sep 08 peter 328
1541 30 Sep 08 peter 329     /**
3501 31 May 16 peter 330        \return * \a iter
1541 30 Sep 08 peter 331     */
2202 21 Feb 10 peter 332     data_reference data(Iter iter) const { return *iter; }
1541 30 Sep 08 peter 333
1541 30 Sep 08 peter 334     /**
2202 21 Feb 10 peter 335        \return 1.0
1541 30 Sep 08 peter 336     */
2202 21 Feb 10 peter 337     weight_reference weight(Iter iter) const { return 1.0; }
1382 17 Jul 08 peter 338   };
1382 17 Jul 08 peter 339
2202 21 Feb 10 peter 340   /**
2202 21 Feb 10 peter 341      \internal
2202 21 Feb 10 peter 342      Metafunction that returns double& if true and const double otherwise
2202 21 Feb 10 peter 343    */
2202 21 Feb 10 peter 344   template<bool>
2202 21 Feb 10 peter 345   struct mutable_reference {
2202 21 Feb 10 peter 346     /// return const double if bool is false
2202 21 Feb 10 peter 347     typedef const double type;
2202 21 Feb 10 peter 348   };
1382 17 Jul 08 peter 349
1382 17 Jul 08 peter 350   /**
2202 21 Feb 10 peter 351      \internal
2202 21 Feb 10 peter 352      Specialization that returns double& in true case
2202 21 Feb 10 peter 353   */
2202 21 Feb 10 peter 354   template<>
2202 21 Feb 10 peter 355   struct mutable_reference<true> {
2202 21 Feb 10 peter 356     /// return double& if bool is false
2202 21 Feb 10 peter 357     typedef double& type;
2202 21 Feb 10 peter 358   };
2202 21 Feb 10 peter 359
2202 21 Feb 10 peter 360
2202 21 Feb 10 peter 361   /**
2202 21 Feb 10 peter 362      \internal
2202 21 Feb 10 peter 363
2202 21 Feb 10 peter 364      Specialization for weighted iterators
1563 10 Oct 08 peter 365    */
2202 21 Feb 10 peter 366   // we need remove_reference because is_const seems to not work on const&
1563 10 Oct 08 peter 367   template <typename Iter>
3501 31 May 16 peter 368   struct iterator_traits_detail<Iter,
2202 21 Feb 10 peter 369                          typename boost::enable_if<is_weighted<Iter> >::type >
2202 21 Feb 10 peter 370   {
1563 10 Oct 08 peter 371     /**
2202 21 Feb 10 peter 372        data_reference is double& for mutable iterators and const
2202 21 Feb 10 peter 373        double otherwise
1563 10 Oct 08 peter 374     */
3501 31 May 16 peter 375     typedef
3501 31 May 16 peter 376     typename mutable_reference<iter_has_mutable_data<Iter>::value>::type
2202 21 Feb 10 peter 377     data_reference;
1563 10 Oct 08 peter 378
1563 10 Oct 08 peter 379     /**
2202 21 Feb 10 peter 380        weight_reference is double& for mutable iterators and const
2202 21 Feb 10 peter 381        double otherwise
1563 10 Oct 08 peter 382     */
3501 31 May 16 peter 383     typedef
3501 31 May 16 peter 384     typename mutable_reference<iter_has_mutable_weight<Iter>::value>::type
2202 21 Feb 10 peter 385     weight_reference;
1563 10 Oct 08 peter 386
1563 10 Oct 08 peter 387     /**
2202 21 Feb 10 peter 388        return data of \a iter
1563 10 Oct 08 peter 389     */
1563 10 Oct 08 peter 390     data_reference data(Iter iter) const { return (*iter).data(); }
1563 10 Oct 08 peter 391
1563 10 Oct 08 peter 392     /**
2202 21 Feb 10 peter 393        return weight of \a iter
1563 10 Oct 08 peter 394     */
1563 10 Oct 08 peter 395     weight_reference weight(Iter iter) const { return (*iter).weight(); }
1563 10 Oct 08 peter 396   };
2202 21 Feb 10 peter 397
1591 17 Oct 08 peter 398 } // namespace detail
1563 10 Oct 08 peter 399
3188 25 Mar 14 peter 400 /// \endcond
3188 25 Mar 14 peter 401
3188 25 Mar 14 peter 402
1563 10 Oct 08 peter 403   /**
1541 30 Sep 08 peter 404      The purpose of this class is to allow polymorphism between
1541 30 Sep 08 peter 405      weighted and unweighted iterators. It allows to access data and
1541 30 Sep 08 peter 406      weight for both weighted and unweighted iterators.
1541 30 Sep 08 peter 407
2202 21 Feb 10 peter 408      For weighted iterators this class requires that *Iter has
2202 21 Feb 10 peter 409      functions data(void) and weight(void).
3501 31 May 16 peter 410    */
1541 30 Sep 08 peter 411   template <typename Iter>
1541 30 Sep 08 peter 412   struct iterator_traits {
1541 30 Sep 08 peter 413   private:
2202 21 Feb 10 peter 414     typedef detail::iterator_traits_detail<Iter> traits;
1541 30 Sep 08 peter 415   public:
1382 17 Jul 08 peter 416     /**
2202 21 Feb 10 peter 417        For unweighted iterator, data_reference is the same as
2202 21 Feb 10 peter 418        std::iterator_traits<Iter>::reference, i.e., the data if the
2202 21 Feb 10 peter 419        iterator is the same as *Iter.
2202 21 Feb 10 peter 420
2202 21 Feb 10 peter 421        For weighted iterators, data_reference is double& if *Iter has
2202 21 Feb 10 peter 422        a function double& data(void). Otherwise data_reference is
2202 21 Feb 10 peter 423        const double.
1382 17 Jul 08 peter 424      */
1541 30 Sep 08 peter 425     typedef typename traits::data_reference data_reference;
1382 17 Jul 08 peter 426
1382 17 Jul 08 peter 427     /**
2472 12 Apr 11 peter 428        For unweighted iterator, weight_reference is const double since
2472 12 Apr 11 peter 429        the weight is always implicitly 1.0 and not mutable.
2202 21 Feb 10 peter 430
2472 12 Apr 11 peter 431        For weighted iterators, weight_reference is double& if *Iter has
2472 12 Apr 11 peter 432        a function double& weight(void). Otherwise weight_reference is
2202 21 Feb 10 peter 433        const double.
1382 17 Jul 08 peter 434      */
1541 30 Sep 08 peter 435     typedef typename traits::weight_reference weight_reference;
1382 17 Jul 08 peter 436
1382 17 Jul 08 peter 437     /**
2202 21 Feb 10 peter 438        \return data of iterator \a iter
1382 17 Jul 08 peter 439     */
3501 31 May 16 peter 440     data_reference data(Iter iter) const
1541 30 Sep 08 peter 441     { return traits().data(iter); }
1382 17 Jul 08 peter 442
1382 17 Jul 08 peter 443     /**
2202 21 Feb 10 peter 444        \return weight of iterator \a iter
1541 30 Sep 08 peter 445      */
3501 31 May 16 peter 446     weight_reference weight(Iter iter) const
1541 30 Sep 08 peter 447     { return traits().weight(iter); }
1382 17 Jul 08 peter 448
1382 17 Jul 08 peter 449   };
1382 17 Jul 08 peter 450
908 28 Sep 07 peter 451 }}} // of namespace utility, yat, and theplu
908 28 Sep 07 peter 452
908 28 Sep 07 peter 453 #endif