[06/10,gdbsupport] Factor out base_next_iterator
Commit Message
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++.
I also explored using a pointer-to-member template argument T::next:
...
template<typename T, auto F = &T::next>
struct next_iterator
{
...
self_type &operator++ ()
{
m_item = m_item->*F;
return *this;
}
...
}
...
but that meant that using an incomplete T was no longer allowed (see
test_next_iterator_incomplete_type), so it's not a drop-in replacement.
---
gdbsupport/next-iterator.h | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
Comments
>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:
Tom> + m_item = static_cast<D *>(this)->next ();
Space before paren.
Tom
@@ -21,27 +21,27 @@
#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 a next
+ function, which determines the actual field that is iterated over. */
-template<typename T>
-struct next_iterator
+template<typename T, class D>
+struct base_next_iterator
{
- using self_type = next_iterator;
+ using self_type = base_next_iterator;
using value_type = T *;
using reference = T *&;
using pointer = T **;
using iterator_category = std::forward_iterator_tag;
using difference_type = int;
- 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)
{
}
@@ -63,15 +63,31 @@ struct next_iterator
self_type &operator++ ()
{
- m_item = m_item->next;
+ m_item = static_cast<D *>(this)->next ();
return *this;
}
-private:
+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. Note that we're using CRTP here. */
+
+template<typename T>
+struct next_iterator : base_next_iterator<T, next_iterator<T>>
+{
+ using base_next_iterator<T, next_iterator<T>>::base_next_iterator;
+ using base_next_iterator<T, next_iterator<T>>::m_item;
+
+ T *next ()
+ {
+ return m_item->next;
+ }
+};
+
/* A convenience wrapper to make a range type around a next_iterator. */
template <typename T>