aimsdata 6.0.0
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
7namespace 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
72 {
73 ++m_iterator;
74 if (m_iterator == m_end) m_iterator = m_begin;
75 }
76
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_ */
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)
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)
std::iterator_traits< TIterator >::reference operator*()
const std::iterator_traits< TIterator >::reference operator*() const
The class for EcatSino data write operation.
TIterator cyclic_advance(TIterator i, TContainer &c)