aboutsummaryrefslogtreecommitdiff
path: root/gcc/iterator-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/iterator-utils.h')
-rw-r--r--gcc/iterator-utils.h73
1 files changed, 73 insertions, 0 deletions
diff --git a/gcc/iterator-utils.h b/gcc/iterator-utils.h
index a3f7dd5..af1463b 100644
--- a/gcc/iterator-utils.h
+++ b/gcc/iterator-utils.h
@@ -200,4 +200,77 @@ list_iterator<T, Next>::operator++ (int)
return ret;
}
+// An iterator that pre-computes the next value if we haven't already got to the
+// end. This is useful in cases where a standard iterator would get invalidated
+// (e.g. elements getting removed from a container) during the body of a loop.
+template<typename T>
+class safe_iterator
+{
+ T m_current;
+ const T m_end;
+ T m_next;
+
+ T get_next ()
+ {
+ if (m_current != m_end)
+ {
+ // FIXME: we should use std::next here but that would mean having
+ // #include <iterator> everywhere that iterator-utils.h is included.
+ //
+ // For now we just implement it directly.
+ T iter = m_current;
+ return ++iter;
+ }
+ return m_end;
+ }
+
+ void advance ()
+ {
+ m_current = m_next;
+ if (m_next != m_end)
+ ++m_next;
+ }
+
+public:
+ bool operator== (const safe_iterator &other) const
+ {
+ return m_current == other.m_current;
+ }
+
+ bool operator!= (const safe_iterator &other) const
+ {
+ return m_current != other.m_current;
+ }
+
+ typename T::value_type operator*() const { return *m_current; }
+
+ safe_iterator &operator++ ()
+ {
+ advance ();
+ return *this;
+ }
+
+ safe_iterator operator++ (int)
+ {
+ auto ret = *this;
+ advance ();
+ return ret;
+ }
+
+ safe_iterator (T iter, T end)
+ : m_current (iter), m_end (end), m_next (get_next ()) {}
+};
+
+// Convert a container RANGE into a container of safe_iterators.
+template<typename Container>
+inline
+iterator_range<safe_iterator<typename Container::const_iterator>>
+iterate_safely (Container range)
+{
+ return {
+ { range.begin (), range.end () },
+ { range.end (), range.end () }
+ };
+}
+
#endif