GCC Middle and Back End API Reference
iterator-utils.h
Go to the documentation of this file.
1// Iterator-related utilities.
2// Copyright (C) 2002-2024 Free Software Foundation, Inc.
3//
4// This file is part of GCC.
5//
6// GCC is free software; you can redistribute it and/or modify it under
7// the terms of the GNU General Public License as published by the Free
8// Software Foundation; either version 3, or (at your option) any later
9// version.
10//
11// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12// WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with GCC; see the file COPYING3. If not see
18// <http://www.gnu.org/licenses/>.
19
20#ifndef GCC_ITERATOR_UTILS_H
21#define GCC_ITERATOR_UTILS_H 1
22
23// A half-open [begin, end) range of iterators.
24template<typename T>
26{
27public:
29
30 iterator_range () = default;
31 iterator_range (const T &begin, const T &end)
32 : m_begin (begin), m_end (end) {}
33
34 T begin () const { return m_begin; }
35 T end () const { return m_end; }
36
37 explicit operator bool () const { return m_begin != m_end; }
38
39private:
42};
43
44// Provide an iterator like BaseIT, except that it yields values of type T,
45// which is derived from the type that BaseIT normally yields.
46//
47// The class doesn't inherit from BaseIT for two reasons:
48// - using inheritance would stop the class working with plain pointers
49// - not using inheritance increases type-safety for writable iterators
50//
51// Constructing this class from a BaseIT involves an assertion that all
52// contents really do have type T. The constructor is therefore explicit.
53template<typename T, typename BaseIT>
55{
56public:
57 using value_type = T;
58
59 derived_iterator () = default;
60
61 template<typename... Ts>
62 explicit derived_iterator (Ts... args)
63 : m_base (std::forward<Ts> (args)...) {}
64
65 derived_iterator &operator++ () { ++m_base; return *this; }
67
68 T operator* () const { return static_cast<T> (*m_base); }
69 T *operator-> () const { return static_cast<T *> (m_base.operator-> ()); }
70
71 bool operator== (const derived_iterator &other) const;
72 bool operator!= (const derived_iterator &other) const;
73
74protected:
75 BaseIT m_base;
76};
77
78template<typename T, typename BaseIT>
81{
82 derived_iterator ret = *this;
83 ++m_base;
84 return ret;
85}
86
87template<typename T, typename BaseIT>
88inline bool
90{
91 return m_base == other.m_base;
92}
93
94template<typename T, typename BaseIT>
95inline bool
97{
98 return m_base != other.m_base;
99}
100
101// Provide a constant view of a BaseCT in which every value is known to
102// have type T, which is derived from the type that BaseCT normally presents.
103//
104// Constructing this class from a BaseCT involves an assertion that all
105// contents really do have type T. The constructor is therefore explicit.
106template<typename T, typename BaseCT>
107class const_derived_container : public BaseCT
108{
109 using base_const_iterator = typename BaseCT::const_iterator;
110
111public:
112 using value_type = T;
114
116
117 template<typename... Ts>
118 explicit const_derived_container (Ts... args)
119 : BaseCT (std::forward<Ts> (args)...) {}
120
121 const_iterator begin () const { return const_iterator (BaseCT::begin ()); }
122 const_iterator end () const { return const_iterator (BaseCT::end ()); }
123
124 T front () const { return static_cast<T> (BaseCT::front ()); }
125 T back () const { return static_cast<T> (BaseCT::back ()); }
126 T operator[] (unsigned int i) const;
127};
128
129template<typename T, typename BaseCT>
130inline T
132{
133 return static_cast<T> (BaseCT::operator[] (i));
134}
135
136// A base class for iterators whose contents consist of a StoredT and that
137// when dereferenced yield those StoredT contents as a T. Derived classes
138// should implement at least operator++ or operator--.
139template<typename T, typename StoredT = T>
141{
142public:
143 using value_type = T;
144
145 wrapper_iterator () = default;
146
147 template<typename... Ts>
148 wrapper_iterator (Ts... args) : m_contents (std::forward<Ts> (args)...) {}
149
150 T operator* () const { return static_cast<T> (m_contents); }
151 bool operator== (const wrapper_iterator &) const;
152 bool operator!= (const wrapper_iterator &) const;
153
154protected:
155 StoredT m_contents;
156};
157
158template<typename T, typename StoredT>
159inline bool
161{
162 return m_contents == other.m_contents;
163}
164
165template<typename T, typename StoredT>
166inline bool
168{
169 return m_contents != other.m_contents;
170}
171
172// A forward iterator for a linked list whose nodes are referenced using
173// type T. Given a node "T N", the next element is given by (N->*Next) ().
174template<typename T, T *(T::*Next) () const>
176{
177private:
179
180public:
181 using parent::parent;
184};
185
186template<typename T, T *(T::*Next) () const>
189{
190 this->m_contents = (this->m_contents->*Next) ();
191 return *this;
192}
193
194template<typename T, T *(T::*Next) () const>
197{
198 list_iterator ret = *this;
199 this->m_contents = (this->m_contents->*Next) ();
200 return ret;
201}
202
203// An iterator that pre-computes the next value if we haven't already got to the
204// end. This is useful in cases where a standard iterator would get invalidated
205// (e.g. elements getting removed from a container) during the body of a loop.
206template<typename T>
208{
210 const T m_end;
212
214 {
215 if (m_current != m_end)
216 {
217 // FIXME: we should use std::next here but that would mean having
218 // #include <iterator> everywhere that iterator-utils.h is included.
219 //
220 // For now we just implement it directly.
221 T iter = m_current;
222 return ++iter;
223 }
224 return m_end;
225 }
226
227 void advance ()
228 {
230 if (m_next != m_end)
231 ++m_next;
232 }
233
234public:
235 bool operator== (const safe_iterator &other) const
236 {
237 return m_current == other.m_current;
238 }
239
240 bool operator!= (const safe_iterator &other) const
241 {
242 return m_current != other.m_current;
243 }
244
245 typename T::value_type operator*() const { return *m_current; }
246
248 {
249 advance ();
250 return *this;
251 }
252
254 {
255 auto ret = *this;
256 advance ();
257 return ret;
258 }
259
260 safe_iterator (T iter, T end)
261 : m_current (iter), m_end (end), m_next (get_next ()) {}
262};
263
264// Convert a container RANGE into a container of safe_iterators.
265template<typename Container>
266inline
268iterate_safely (Container range)
269{
270 return {
271 { range.begin (), range.end () },
272 { range.end (), range.end () }
273 };
274}
275
276#endif
Definition iterator-utils.h:108
T back() const
Definition iterator-utils.h:125
const_iterator begin() const
Definition iterator-utils.h:121
const_derived_container()=default
const_derived_container(Ts... args)
Definition iterator-utils.h:118
typename BaseCT::const_iterator base_const_iterator
Definition iterator-utils.h:109
T operator[](unsigned int i) const
Definition iterator-utils.h:131
T value_type
Definition iterator-utils.h:112
derived_iterator< T, base_const_iterator > const_iterator
Definition iterator-utils.h:113
T front() const
Definition iterator-utils.h:124
const_iterator end() const
Definition iterator-utils.h:122
Definition iterator-utils.h:55
bool operator!=(const derived_iterator &other) const
Definition iterator-utils.h:96
T * operator->() const
Definition iterator-utils.h:69
derived_iterator(Ts... args)
Definition iterator-utils.h:62
T operator*() const
Definition iterator-utils.h:68
derived_iterator()=default
derived_iterator & operator++()
Definition iterator-utils.h:65
bool operator==(const derived_iterator &other) const
Definition iterator-utils.h:89
BaseIT m_base
Definition iterator-utils.h:75
T value_type
Definition iterator-utils.h:57
Definition iterator-utils.h:176
list_iterator & operator++()
Definition iterator-utils.h:188
Definition iterator-utils.h:208
void advance()
Definition iterator-utils.h:227
T get_next()
Definition iterator-utils.h:213
const T m_end
Definition iterator-utils.h:210
safe_iterator & operator++()
Definition iterator-utils.h:247
safe_iterator(T iter, T end)
Definition iterator-utils.h:260
T m_next
Definition iterator-utils.h:211
bool operator==(const safe_iterator &other) const
Definition iterator-utils.h:235
T m_current
Definition iterator-utils.h:209
T::value_type operator*() const
Definition iterator-utils.h:245
bool operator!=(const safe_iterator &other) const
Definition iterator-utils.h:240
Definition iterator-utils.h:141
T value_type
Definition iterator-utils.h:143
wrapper_iterator()=default
T operator*() const
Definition iterator-utils.h:150
wrapper_iterator(Ts... args)
Definition iterator-utils.h:148
bool operator==(const wrapper_iterator &) const
Definition iterator-utils.h:160
bool operator!=(const wrapper_iterator &) const
Definition iterator-utils.h:167
StoredT m_contents
Definition iterator-utils.h:155
static struct token T
Definition gengtype-parse.cc:45
iterator_range< safe_iterator< typename Container::const_iterator > > iterate_safely(Container range)
Definition iterator-utils.h:268
i
Definition poly-int.h:776
Definition iterator-utils.h:26
T end() const
Definition iterator-utils.h:35
T begin() const
Definition iterator-utils.h:34
T m_begin
Definition iterator-utils.h:40
T m_end
Definition iterator-utils.h:41
iterator_range(const T &begin, const T &end)
Definition iterator-utils.h:31
iterator_range()=default
T const_iterator
Definition iterator-utils.h:28
#define bool
Definition system.h:886
T * end(vec< T, A, L > *v)
Definition vec.h:457