source: trunk/yat/utility/WeightedIterator.h

Last change on this file was 3461, checked in by Peter, 6 years ago

docs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1#ifndef _theplu_yat_utility_weighted_iterator_
2#define _theplu_yat_utility_weighted_iterator_
3
4// $Id: WeightedIterator.h 3461 2016-01-22 01:29:13Z peter $
5
6/*
7  Copyright (C) 2008, 2009, 2010, 2016 Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "DataWeight.h"
26#include "DataWeightProxy.h"
27
28#include <boost/iterator/is_readable_iterator.hpp>
29#include <boost/iterator/iterator_facade.hpp>
30#include <boost/mpl/and.hpp>
31#include <boost/mpl/bool.hpp>
32#include <boost/mpl/eval_if.hpp>
33#include <boost/type_traits/is_convertible.hpp>
34#include <boost/utility/enable_if.hpp>
35
36#include <iterator>
37
38namespace theplu {
39namespace yat {
40namespace utility {
41
42  namespace detail {
43    namespace weighted_iterator {
44
45      /// Determines which traversal concept (see boost iterator
46      /// traversal concept) the WeightedIterator is marked as. The
47      /// class looks at iterator_traversal from DataIterator and
48      /// WeightIterator and returns the simplest of them (e.g. if
49      /// DataIterator is bidirectional_iterator and WeightIterator is
50      /// forward_iterator, then forward_iterator will be returned).
51      template<typename DataIterator, typename WeightIterator>
52      class Traversal
53      {
54        typedef typename boost::iterator_traversal<DataIterator>::type T1;
55        typedef typename boost::iterator_traversal<WeightIterator>::type T2;
56      public:
57        /// \return the least advanced type
58        /// if T1 is convertible to T2 (T1 is more advanced) return T2
59        typedef typename boost::mpl::if_<
60          boost::is_convertible<T1, T2>, T2, T1>::type type;
61      };
62
63    } // end of weighted_iterator namespace
64  } // end of detail namespace
65
66  /**
67     \brief WeightedIterator
68
69     Adaptor enabling to make two unweighted iterators to behave like
70     a \ref concept_weighted_iterator. The data part corresponds to
71     the data_iterator and the weight corresponds to the
72     weight_iterator.
73
74     \c WeightedIterator is a \ref concept_weighted_iterator and its
75     \c value_type is \c DataWeight. However due to the nature of this
76     adaptor there are no physical \c DataWeight in memory that \c
77     WeightedIterator points to, so its \c reference_type is not \c
78     DataWeight& but a \c DataWeightProxy. As a proxy is used, which
79     is not allowed in a \forward_iterator, WeightedIterator is a
80     \input_iterator.
81
82     Although WeightedIterator is tagged a \input_iterator, more
83     advanced traversal is implemented if supported by underlying
84     iterators. If underlying iterators support random access
85     traversal, e.g., WeightedIterator supports it as well and
86     boost::iterator_traversal<T>::type is set appropriately (see
87     \random_access_traversal_iterator).
88
89     Type Requirements:
90     - \c DataWeightProxy<DataIterator, WeightIterator> is a valid
91     expression.
92  */
93  template<typename DataIterator, typename WeightIterator>
94  class WeightedIterator
95    : public boost::iterator_facade<
96    WeightedIterator<DataIterator, WeightIterator>,
97    DataWeight,
98    typename
99    detail::weighted_iterator::Traversal<DataIterator, WeightIterator>::type,
100    DataWeightProxy<DataIterator, WeightIterator> >
101
102  {
103  public:
104    /**
105       \brief DataIterator
106     */
107    typedef DataIterator data_iterator;
108
109    /**
110       \brief DataIterator
111     */
112    typedef WeightIterator weight_iterator;
113
114    /**
115       \brief Default Constructor.
116
117       Created iterator is not dereferencable
118
119       \since New in yat 0.6
120    */
121    WeightedIterator(void)
122    {}
123
124    /**
125       \brief Constructor
126     */
127    WeightedIterator(DataIterator d, WeightIterator w)
128      : d_iter_(d), w_iter_(w)
129    {}
130
131    /**
132       \return const reference to underlying data iterator
133     */
134    const DataIterator& data_base(void) const { return d_iter_; }
135
136    /**
137       \return const reference to underlying weight iterator
138     */
139    const WeightIterator& weight_base(void) const { return w_iter_; }
140
141    /**
142       \brief element operator
143     */
144    DataWeightProxy<DataIterator, WeightIterator> operator[](int n) const
145    {
146      return DataWeightProxy<DataIterator, WeightIterator>(d_iter_+n,
147                                                           w_iter_+n);
148    }
149
150
151    /**
152       \brief Conversion constructor.
153
154       Create a WeightIterator<Base> from a
155       WeightIterator<B2>. Possible if B2 is convertible to a
156       Base. Constructor allows implicit conversions such as iterator
157       to const_iterator.
158     */
159    template<typename D2, typename W2>
160    WeightedIterator(WeightedIterator<D2, W2> other,
161            typename boost::enable_if_convertible<D2,DataIterator>::type* = 0,
162            typename boost::enable_if_convertible<W2,WeightIterator>::type* = 0)
163      : d_iter_(other.data_base()), w_iter_(other.weight_base()) {}
164
165
166  private:
167    friend class boost::iterator_core_access;
168
169    DataIterator d_iter_;
170    WeightIterator w_iter_;
171
172    void advance(size_t n)
173    { std::advance(d_iter_, n); std::advance(w_iter_, n); }
174
175    void decrement(void) { --d_iter_; --w_iter_; }
176
177    typename std::iterator_traits<DataIterator>::difference_type
178    distance_to(const WeightedIterator& other) const
179    { return std::distance(d_iter_, other.d_iter_); }
180
181    utility::DataWeightProxy<DataIterator, WeightIterator>
182    dereference(void) const
183    { return DataWeightProxy<DataIterator, WeightIterator>(d_iter_,
184                                                           w_iter_);
185    }
186
187    bool equal(const WeightedIterator& other) const
188    { return d_iter_==other.d_iter_ && w_iter_==other.w_iter_; }
189
190    void increment(void) { ++d_iter_; ++w_iter_; }
191
192  };
193
194  /**
195     \brief convenient function to create WeightedIterator
196
197     Convenient function in same fashion as std::make_pair.
198
199     \relates WeightedIterator
200   */
201  template<typename DataIterator, typename WeightIterator>
202  WeightedIterator<DataIterator, WeightIterator>
203  weighted_iterator(DataIterator data, WeightIterator weight)
204  {
205    return WeightedIterator<DataIterator, WeightIterator>(data, weight);
206  }
207
208}}} // of namespace utility, yat, and theplu
209
210#endif
Note: See TracBrowser for help on using the repository browser.