1 // Iterator-related utilities.
2 // Copyright (C) 2002-2024 Free Software Foundation, Inc.
4 // This file is part of GCC.
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
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
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/>.
20 #ifndef GCC_ITERATOR_UTILS_H
21 #define GCC_ITERATOR_UTILS_H 1
23 // A half-open [begin, end) range of iterators.
28 using const_iterator
= T
;
30 iterator_range () = default;
31 iterator_range (const T
&begin
, const T
&end
)
32 : m_begin (begin
), m_end (end
) {}
34 T
begin () const { return m_begin
; }
35 T
end () const { return m_end
; }
37 explicit operator bool () const { return m_begin
!= m_end
; }
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.
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
51 // Constructing this class from a BaseIT involves an assertion that all
52 // contents really do have type T. The constructor is therefore explicit.
53 template<typename T
, typename BaseIT
>
54 class derived_iterator
59 derived_iterator () = default;
61 template<typename
... Ts
>
62 explicit derived_iterator (Ts
... args
)
63 : m_base (std::forward
<Ts
> (args
)...) {}
65 derived_iterator
&operator++ () { ++m_base
; return *this; }
66 derived_iterator
operator++ (int);
68 T
operator* () const { return static_cast<T
> (*m_base
); }
69 T
*operator-> () const { return static_cast<T
*> (m_base
.operator-> ()); }
71 bool operator== (const derived_iterator
&other
) const;
72 bool operator!= (const derived_iterator
&other
) const;
78 template<typename T
, typename BaseIT
>
79 inline derived_iterator
<T
, BaseIT
>
80 derived_iterator
<T
, BaseIT
>::operator++ (int)
82 derived_iterator ret
= *this;
87 template<typename T
, typename BaseIT
>
89 derived_iterator
<T
, BaseIT
>::operator== (const derived_iterator
&other
) const
91 return m_base
== other
.m_base
;
94 template<typename T
, typename BaseIT
>
96 derived_iterator
<T
, BaseIT
>::operator!= (const derived_iterator
&other
) const
98 return m_base
!= other
.m_base
;
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.
104 // Constructing this class from a BaseCT involves an assertion that all
105 // contents really do have type T. The constructor is therefore explicit.
106 template<typename T
, typename BaseCT
>
107 class const_derived_container
: public BaseCT
109 using base_const_iterator
= typename
BaseCT::const_iterator
;
112 using value_type
= T
;
113 using const_iterator
= derived_iterator
<T
, base_const_iterator
>;
115 const_derived_container () = default;
117 template<typename
... Ts
>
118 explicit const_derived_container (Ts
... args
)
119 : BaseCT (std::forward
<Ts
> (args
)...) {}
121 const_iterator
begin () const { return const_iterator (BaseCT::begin ()); }
122 const_iterator
end () const { return const_iterator (BaseCT::end ()); }
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;
129 template<typename T
, typename BaseCT
>
131 const_derived_container
<T
, BaseCT
>::operator[] (unsigned int i
) const
133 return static_cast<T
> (BaseCT::operator[] (i
));
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--.
139 template<typename T
, typename StoredT
= T
>
140 class wrapper_iterator
143 using value_type
= T
;
145 wrapper_iterator () = default;
147 template<typename
... Ts
>
148 wrapper_iterator (Ts
... args
) : m_contents (std::forward
<Ts
> (args
)...) {}
150 T
operator* () const { return static_cast<T
> (m_contents
); }
151 bool operator== (const wrapper_iterator
&) const;
152 bool operator!= (const wrapper_iterator
&) const;
158 template<typename T
, typename StoredT
>
160 wrapper_iterator
<T
, StoredT
>::operator== (const wrapper_iterator
&other
) const
162 return m_contents
== other
.m_contents
;
165 template<typename T
, typename StoredT
>
167 wrapper_iterator
<T
, StoredT
>::operator!= (const wrapper_iterator
&other
) const
169 return m_contents
!= other
.m_contents
;
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) ().
174 template<typename T
, T
*(T::*Next
) () const>
175 class list_iterator
: public wrapper_iterator
<T
*>
178 using parent
= wrapper_iterator
<T
*>;
181 using parent::parent
;
182 list_iterator
&operator++ ();
183 list_iterator
operator++ (int);
186 template<typename T
, T
*(T::*Next
) () const>
187 inline list_iterator
<T
, Next
> &
188 list_iterator
<T
, Next
>::operator++ ()
190 this->m_contents
= (this->m_contents
->*Next
) ();
194 template<typename T
, T
*(T::*Next
) () const>
195 inline list_iterator
<T
, Next
>
196 list_iterator
<T
, Next
>::operator++ (int)
198 list_iterator ret
= *this;
199 this->m_contents
= (this->m_contents
->*Next
) ();
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.
215 if (m_current
!= m_end
)
217 // FIXME: we should use std::next here but that would mean having
218 // #include <iterator> everywhere that iterator-utils.h is included.
220 // For now we just implement it directly.
235 bool operator== (const safe_iterator
&other
) const
237 return m_current
== other
.m_current
;
240 bool operator!= (const safe_iterator
&other
) const
242 return m_current
!= other
.m_current
;
245 typename
T::value_type
operator*() const { return *m_current
; }
247 safe_iterator
&operator++ ()
253 safe_iterator
operator++ (int)
260 safe_iterator (T iter
, T end
)
261 : m_current (iter
), m_end (end
), m_next (get_next ()) {}
264 // Convert a container RANGE into a container of safe_iterators.
265 template<typename Container
>
267 iterator_range
<safe_iterator
<typename
Container::const_iterator
>>
268 iterate_safely (Container range
)
271 { range
.begin (), range
.end () },
272 { range
.end (), range
.end () }