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

Last change on this file since 3393 was 3393, checked in by Peter, 5 years ago

refs #803

The std::random_access_iterator promises that iterator provides random
traversal and that reference_type is an lvalue (i.e. not proxy). If
reference_type is a proxy, it is therefore incorrect to tag the
iterator with std::random_access_iterator. To reflect that we do the
following two changes:

1) Container2DIterator now carries tag
boost::random_access_traversal_tag rather than
std::random_access_iterator. This means that in std:: speak a
Container2DIterator is a random access iterator, if reference is an
lvalue and an input iterator otherwise.

2) The BASE of StrideIterator? is no longer required to be a random
access iterator, instead we require random access traversal.
Therefore, StrideIterator? now uses the default tag rather than
std::iterator_traits<BASE>::iterator_category. This means that the
traversal tag is boost::random_access_traversal_tag (as BASE is
required to provide random access traversal), and in std:: speak the
same rule applies as for Container2DIterator.

3) The concept check for Container2D now requires that iterators
::const_iterator, ::const_row_iterator, ::const_column_iterator are
readable iterator (the random access requirement is removed).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svndigest:ignore set to 1037
File size: 4.3 KB
RevLine 
[1038]1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
[880]3
4// $Id: StrideIterator.h 3393 2015-03-17 03:38:36Z peter $
5
6/*
[2119]7  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
[2202]8  Copyright (C) 2010 Peter Johansson
[880]9
[1437]10  This file is part of the yat library, http://dev.thep.lu.se/yat
[880]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
[1486]14  published by the Free Software Foundation; either version 3 of the
[880]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
[1487]23  along with yat. If not, see <http://www.gnu.org/licenses/>.
[880]24*/
25
[2202]26#include <boost/concept_check.hpp>
[1386]27#include <boost/iterator/iterator_adaptor.hpp>
[3393]28#include <boost/iterator/iterator_concepts.hpp>
[1386]29
[880]30namespace theplu {
31namespace yat {
32namespace utility {
33
[1038]34  /**
[1041]35     @brief Adaptor using a stride on underlying iterator
36
37     Works as underlying iterator except that all arithmetic uses the
38     stride, so e.g., ++StrideIterator returns underlying
39     _iterator+stride
40
[2183]41     The stride must be positive. Negative stride can be accomplished
42     by combining StrideIterator with a reverse_iterator (from
43     e.g. std or boost).
[3393]44
45     Type Requirements:
46     - \c RandomAccessIterator must be a \readable_iterator
47     - \c RandomAccessIterator must be a \random_access_traversal_iterator
[880]48  */
[2202]49  template<typename RandomAccessIterator>
[1038]50  class StrideIterator 
[2202]51    : public boost::iterator_adaptor<StrideIterator<RandomAccessIterator>
[3393]52                                     , RandomAccessIterator>
[880]53  {
[2202]54    typedef boost::iterator_adaptor<StrideIterator<RandomAccessIterator>,
[3393]55                                    RandomAccessIterator>
[2365]56    super_t;
[1490]57
[880]58  public:
[1125]59    /// type of underlying iterator
[2202]60    typedef RandomAccessIterator iterator_type;
[1490]61
[880]62    /**
[1378]63       \brief default constructor
64
65       Using default constructor of BASE iterator.
66     */
[1490]67    explicit StrideIterator(size_t stride=1)
[2202]68      : StrideIterator::iterator_adaptor_(), stride_(stride) 
69    {
[3393]70      using boost_concepts::RandomAccessTraversal;
71      using boost_concepts::ReadableIterator;
72      BOOST_CONCEPT_ASSERT((ReadableIterator<RandomAccessIterator>));
73      BOOST_CONCEPT_ASSERT((RandomAccessTraversal<RandomAccessIterator>));
[2202]74    }
[1378]75
76    /**
[884]77       \brief Constructor
78    */
[2202]79    explicit StrideIterator(RandomAccessIterator p, size_t stride=1)
[1390]80      : StrideIterator::iterator_adaptor_(p), stride_(stride) {}
[880]81
[1041]82   
83    /**
[1490]84       \brief Copy constructor
85     */
86    StrideIterator(const StrideIterator& other)
87      : StrideIterator::iterator_adaptor_(other.base()), stride_(other.stride()) 
88    {}
89
90    /**
[1386]91       \brief Conversion constructor.
92
[2202]93       Create a StrideIterator<RandomAccessIterator> from a
94       StrideIterator<I2>. Possible if I2 is convertible to a
95       RandomAccessIterator. Constructor allows implicit conversions
96       such as iterator to const_iterator.
[1041]97     */
[1386]98    template<typename I2>
99    StrideIterator(StrideIterator<I2> other,
[2202]100                   typename boost::enable_if_convertible<I2
101                   , RandomAccessIterator>::type* = 0 )
[1390]102      : StrideIterator::iterator_adaptor_(other.base()), 
103        stride_(other.stride()) {}
[1027]104
[1490]105    /**
106        \brief Assignment operator
107     */
108    StrideIterator& operator=(const StrideIterator& rhs)
109    {
110      stride_ = rhs.stride();
111      this->base_reference() = rhs.base();
112      return *this;
113    }
114
[884]115    /**
[1041]116       \return stride
117     */
118    inline size_t stride(void) const { return stride_; }
119
[1390]120  private:
121    // to give base class access to private parts
122    friend class boost::iterator_core_access;
123   
124    size_t stride_;
[884]125
[1490]126    //typedef typename StrideIterator::iterator_adaptor_::difference_type
[1390]127    typedef typename StrideIterator::iterator_adaptor_::difference_type
128    difference_t;
[1038]129
[1490]130    void advance(typename super_t::difference_type n)
131    { this->base_reference() += stride_*n; }
132
[1390]133    void decrement(void) { this->base_reference()-=stride_; }
[932]134
[1390]135    template <class OtherIterator>
[1490]136    typename super_t::difference_type
137    distance_to(const StrideIterator<OtherIterator>& other) const
138    { 
139      // casting to int to avoid loss of sign in numerator
140      return (other.base() - this->base() )/static_cast<int>(stride_); 
141    }
[884]142
[1390]143    void increment(void) { this->base_reference()+=stride_; }
[880]144  };
[1041]145
[880]146}}} // of namespace utility, yat, and theplu
147
148#endif
Note: See TracBrowser for help on using the repository browser.