source: trunk/yat/utility/StrideIterator.h @ 1390

Last change on this file since 1390 was 1390, checked in by Peter, 13 years ago

fixing #402. Making StrideIterator? inherit from boost::iterator_adaptor solved the problem.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.6 KB
Line 
1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
3
4// $Id: StrideIterator.h 1390 2008-07-28 02:42:13Z peter $
5
6/*
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2008 Peter Johansson
9
10  This file is part of the yat library, http://trac.thep.lu.se/yat
11
12  The yat library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License as
14  published by the Free Software Foundation; either version 2 of the
15  License, or (at your option) any later version.
16
17  The yat library is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  General Public License for more details.
21
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25  02111-1307, USA.
26*/
27
28#include "iterator_traits.h"
29
30#include <boost/iterator/iterator_adaptor.hpp>
31
32namespace theplu {
33namespace yat {
34namespace utility {
35
36  // forward declaration
37  template<typename Iter>
38  class StrideIterator;
39
40  /**
41     Specialization for StrideIterator that calls underlying iterator.
42   */
43  template <typename Iter>
44  struct weighted_iterator_traits<StrideIterator<Iter> > {
45    /**
46       StrideIterator is weighted if underlying iterator is weighted.
47    */
48    typedef typename weighted_iterator_traits<Iter>::type type;
49  };
50
51  /**
52     Specialization for StrideIterator using iterator_traits with base()
53   */
54  template <class Iter>
55  struct iterator_traits<StrideIterator<Iter> > {
56    /**
57       data_reference same as for underlying iterator
58     */
59    typedef typename iterator_traits<Iter>::data_reference data_reference;
60
61    /**
62       weight_reference same as for underlying iterator
63     */
64    typedef typename iterator_traits<Iter>::weight_reference weight_reference;
65
66    /**
67       \return data of iterator
68    */
69    data_reference data(StrideIterator<Iter> iter) const 
70    { return iterator_traits<Iter>().data(iter.base()); }
71
72    /**
73       \return weight of iterator
74    */
75    weight_reference weight(StrideIterator<Iter> iter) const 
76    { return iterator_traits<Iter>().weight(iter.base()); }
77
78  };
79
80  /**
81     @brief Adaptor using a stride on underlying iterator
82
83     Works as underlying iterator except that all arithmetic uses the
84     stride, so e.g., ++StrideIterator returns underlying
85     _iterator+stride
86
87  */
88  template<typename Iter>
89  class StrideIterator 
90    : public boost::iterator_adaptor<StrideIterator<Iter>, Iter>
91  {
92  public:
93    /// type of underlying iterator
94    typedef Iter iterator_type;
95    /// value type
96    typedef typename std::iterator_traits<Iter>::value_type value_type;
97    /// difference type
98    typedef typename std::iterator_traits<Iter>::difference_type difference_type;
99    /// reference
100    typedef typename std::iterator_traits<Iter>::reference reference;
101    /// pointer
102    typedef typename std::iterator_traits<Iter>::pointer pointer;
103    /// weighted_iterator_tag if iterator is weighted
104    typedef typename yat::utility::weighted_iterator_traits<Iter>::type w_type;
105
106    /**
107       \brief default constructor
108
109       Using default constructor of BASE iterator.
110     */
111    StrideIterator(size_t stride=1)
112      : StrideIterator::iterator_adaptor_(), stride_(stride) {}
113
114    /**
115       \brief Constructor
116    */
117    explicit StrideIterator(Iter p, size_t stride=1)
118      : StrideIterator::iterator_adaptor_(p), stride_(stride) {}
119
120   
121    /**
122       \brief Conversion constructor.
123
124       Create a StrideIterator<Iter> from a StrideIterator<I2>. Possible
125       if I2 is convertible to a Iter. Constructor allows implicit
126       conversions such as iterator to const_iterator.
127     */
128    template<typename I2>
129    StrideIterator(StrideIterator<I2> other,
130                   typename boost::enable_if_convertible<I2, Iter>::type* = 0 )
131      : StrideIterator::iterator_adaptor_(other.base()), 
132        stride_(other.stride()) {}
133
134    /**
135       \return stride
136     */
137    inline size_t stride(void) const { return stride_; }
138
139  private:
140    // to give base class access to private parts
141    friend class boost::iterator_core_access;
142   
143    size_t stride_;
144
145    typedef typename StrideIterator::iterator_adaptor_::difference_type
146    difference_t;
147
148    void advance(difference_t n){ this->base_reference() += stride_*n; }
149    void decrement(void) { this->base_reference()-=stride_; }
150
151    template <class OtherIterator>
152    difference_t distance_type(const StrideIterator<OtherIterator>& other) const
153    { return (other.base() - this->base())/stride_; }
154
155    void increment(void) { this->base_reference()+=stride_; }
156
157    // Using compiler generated copy
158    //StrideIterator(const StrideIterator&);
159    //StrideIterator& operator=(const StrideIterator&);
160  };
161
162
163
164
165
166}}} // of namespace utility, yat, and theplu
167
168#endif
Note: See TracBrowser for help on using the repository browser.