]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Factor out base_next_iterator
authorTom de Vries <tdevries@suse.de>
Thu, 23 Apr 2026 06:35:26 +0000 (08:35 +0200)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 30 Apr 2026 15:00:31 +0000 (11:00 -0400)
Template struct next_iterator<T> allows iterating over the "next" field of T.

I decided to generalize this to be able to use any field.

A first thought was to use macros, but nowadays we try to do things more in
native c++, so I didn't explore that further.

Instead, this patch factors out base_next_iterator, which contains all parts
not specific to "next", in other words, everything except the operator++.

Finally, I explored using a pointer-to-member template argument T::next, but
that meant that using an incomplete T was no longer allowed, so it's not
a drop-in replacement.  I also didn't explore this option further, and made
a note of it in the base_next_iterator comment.

gdbsupport/next-iterator.h

index 0c90428d349d9afe9c74a84b116fe50b36c367c1..1dee941a252fd8b0637555e19a728a4b18a600bc 100644 (file)
 
 #include "gdbsupport/iterator-range.h"
 
-/* An iterator that uses the 'next' field of a type to iterate.  This
-   can be used with various GDB types that are stored as linked
-   lists.  */
+/* An iterator base class for iterating over a field of a type.  In order to
+   form a functioning iterator, classes inheriting this should define an
+   operator++, which determines the actual field that is iterated over.
+
+   Instead of factoring out a base class, we could use something like this:
+
+     template<typename T, auto F = &T::next>
+     struct next_iterator
+     {
+       ...
+       self_type &operator++ ()
+       {
+        m_item = m_item->*F;
+        return *this;
+       }
+       ...
+     }
+
+  but that has the drawback that it doesn't work with incomplete T.  */
 
 template<typename T>
-struct next_iterator
+struct base_next_iterator
 {
-  typedef next_iterator self_type;
+  typedef base_next_iterator self_type;
   typedef T *value_type;
   typedef T *&reference;
   typedef T **pointer;
   typedef std::forward_iterator_tag iterator_category;
   typedef int difference_type;
 
-  explicit next_iterator (T *item)
+  explicit base_next_iterator (T *item)
     : m_item (item)
   {
   }
 
   /* Create a one-past-the-end iterator.  */
-  next_iterator ()
+  base_next_iterator ()
     : m_item (nullptr)
   {
   }
@@ -61,15 +77,34 @@ struct next_iterator
     return m_item != other.m_item;
   }
 
-  self_type &operator++ ()
+protected:
+
+  T *m_item;
+};
+
+/* An iterator that uses the 'next' field of a type to iterate.  This
+   can be used with various GDB types that are stored as linked
+   lists.  */
+
+template<typename T>
+struct next_iterator : base_next_iterator<T> {
+  typedef next_iterator self_type;
+  typedef T *value_type;
+  typedef T *&reference;
+  typedef T **pointer;
+
+  explicit next_iterator (T *item)
+    : base_next_iterator<T> (item)
   {
-    m_item = m_item->next;
-    return *this;
   }
 
-private:
+  next_iterator () = default;
 
-  T *m_item;
+  self_type &operator++ ()
+  {
+    this->m_item = this->m_item->next;
+    return *this;
+  }
 };
 
 /* A convenience wrapper to make a range type around a next_iterator.  */