aimsdata  5.1.2
Neuroimaging data handling
cyclic_iterator.h
Go to the documentation of this file.
1 #ifndef AIMS_UTILITY_CYCLIC_ITERATOR_H_
2 #define AIMS_UTILITY_CYCLIC_ITERATOR_H_
3 
4 /* Originally from Catier's aims-til library
5 */
6 
7 namespace aims
8 {
9 
10  //---------------------------------------------------------------------------
11 
12  template < typename TContainer, typename TIterator >
13  inline TIterator cyclic_advance(TIterator i, TContainer &c)
14  {
15  if (++i == c.end()) i = c.begin();
16  return i;
17  }
18 
19  //---------------------------------------------------------------------------
20 
21  namespace detail
22  {
23 
24  //-------------------------------------------------------------------------
25 
26 
30  // We don't derive from the iterator anymore, for several reasons. The first is that TIterator might
31  // be a naked pointer, as it is the case for boost::array. Although, of course, one could specialize
32  // cyclic_iterator for pointers. The second reason is that this is not safe to expose functionality
33  // of the old iterator, as some functions may be broken for the cyclic iterator. In other words, we
34  // expose the part of what we know should work. The other functionality can be retrieve with explicit
35  // getting of the underlying iterator. Of course this is not ideal as well, because in some situations, we
36  // would like to use it without knowing we are dealing with a cyclic iterator.
37  template < typename TIterator >
39  // : public TIterator
40  {
41  public: // typedefs -------------------------------------------------------
42 
43  //typedef TIterator Base;
44 
45  public: // constructors ---------------------------------------------------
46 
47  cyclic_iterator_base() : m_iterator(), m_begin(), m_end() {}
48  // TODO: it's not clear whether this should initialise the iterator as well
49  template < typename TContainer >
50  cyclic_iterator_base(TContainer & c) : m_iterator(), m_begin(c.begin()), m_end(c.end()) {}
52  template < typename TContainer >
53  cyclic_iterator_base(TContainer &c, const TIterator & i) : m_iterator(i), m_begin(c.begin()), m_end(c.end())
54  {
55  // we treat end as a special case because it is one very common case where
56  // the user would provide an iterator lying outside the container.
57  // TODO: I guess this won't work with reverse iterators because of the end()...
58  if (m_iterator == m_end) m_iterator = m_begin;
59  }
60 
61  public: // functions ------------------------------------------------------
62 
63  // TODO: operator* does not necessarily return a reference... use a kind of type_of instead.
64 
65  typename std::iterator_traits<TIterator>::reference
66  operator*() { return *m_iterator; }
67 
68  const typename std::iterator_traits<TIterator>::reference
69  operator*() const { return *m_iterator; }
70 
71  void operator++()
72  {
73  ++m_iterator;
74  if (m_iterator == m_end) m_iterator = m_begin;
75  }
76 
77  void operator--()
78  {
79  if (m_iterator == m_begin) m_iterator = m_end;
80  --m_iterator;
81  }
82 
83  bool operator!=(const TIterator &i)
84  {
85  // I am just adding an assert to track eventual problems when a cyclic
86  // iterator was mistakingly put in a 'for' loop and compared to end()
87  assert(i != m_end);
88  return m_iterator != i;
89  }
90 
91  // TODO: overload other functions as well. This is one of the danger of
92  // deriving from a type: you are exposing all methods! E.g. operator+=
93  // still works in the same (non-cyclic) way. This is of course quite a
94  // proble, when we inherit from an unknown (template argument) type...
95 
96 
97  private: // data ----------------------------------------------------------
98 
99  TIterator m_iterator;
100  TIterator m_begin;
101  TIterator m_end;
102  };
103 
104  //-------------------------------------------------------------------------
105 
106  } // namespace detail
107 
108  //---------------------------------------------------------------------------
109 
112  template < typename TContainer >
114  : public detail::cyclic_iterator_base<typename TContainer::const_iterator>
115  {
116  public: // typedefs ---------------------------------------------------------
118  public: // constructors -----------------------------------------------------
120  const_cyclic_iterator(const TContainer & c) : Base(c) {}
121  const_cyclic_iterator(const TContainer & c, const typename TContainer::const_iterator & i) : Base(c,i) {}
122  };
123 
124  //---------------------------------------------------------------------------
125 
128  template < typename TContainer >
130  : public detail::cyclic_iterator_base<typename TContainer::iterator>
131  {
132  public: // typedefs ---------------------------------------------------------
134  public: // constructors -----------------------------------------------------
136  cyclic_iterator(TContainer & c) : Base(c) {}
137  cyclic_iterator(TContainer & c, const typename TContainer::iterator & i) : Base(c, i) {}
138  };
139 
140  //---------------------------------------------------------------------------
141 
142 } // namespace til
143 
144 
145 
146 #endif /* AIMS_UTILITY_CYCLIC_ITERATOR_H_ */
A const cyclic iterator is a const iterator that goes back to the begining of the container when it r...
const_cyclic_iterator(const TContainer &c, const typename TContainer::const_iterator &i)
detail::cyclic_iterator_base< typename TContainer::const_iterator > Base
const_cyclic_iterator(const TContainer &c)
A cyclic iterator is an iterator that goes back to the begining of the container when it reaches the ...
cyclic_iterator(TContainer &c)
cyclic_iterator(TContainer &c, const typename TContainer::iterator &i)
detail::cyclic_iterator_base< typename TContainer::iterator > Base
TODO: when implementing the operator+=, it might be that we need to split the class in different part...
bool operator!=(const TIterator &i)
cyclic_iterator_base(TContainer &c, const TIterator &i)
NB: it is assumed that i does point on one of the element of c (end() accepted)
const std::iterator_traits< TIterator >::reference operator*() const
std::iterator_traits< TIterator >::reference operator*()
The class for EcatSino data write operation.
Definition: borderfiller.h:13
TIterator cyclic_advance(TIterator i, TContainer &c)