c++: ICE on anon struct with base [PR96636]
[official-gcc.git] / gcc / iterator-utils.h
bloba02dfcc3c8fc97b8ebb2200867f44fef5f28123d
1 // Iterator-related utilities.
2 // Copyright (C) 2002-2021 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.
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.
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.
24 template<typename T>
25 struct iterator_range
27 public:
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; }
39 private:
40 T m_begin;
41 T 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
56 public:
57 using value_type = T;
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;
74 protected:
75 BaseIT m_base;
78 template<typename T, typename BaseIT>
79 inline derived_iterator<T, BaseIT>
80 derived_iterator<T, BaseIT>::operator++ (int)
82 derived_iterator ret = *this;
83 ++m_base;
84 return ret;
87 template<typename T, typename BaseIT>
88 inline bool
89 derived_iterator<T, BaseIT>::operator== (const derived_iterator &other) const
91 return m_base == other.m_base;
94 template<typename T, typename BaseIT>
95 inline bool
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;
111 public:
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>
130 inline T
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
142 public:
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;
154 protected:
155 StoredT m_contents;
158 template<typename T, typename StoredT>
159 inline bool
160 wrapper_iterator<T, StoredT>::operator== (const wrapper_iterator &other) const
162 return m_contents == other.m_contents;
165 template<typename T, typename StoredT>
166 inline bool
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 *>
177 private:
178 using parent = wrapper_iterator<T *>;
180 public:
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) ();
191 return *this;
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) ();
200 return ret;
203 #endif