From: Simon Marchi <simark@simark.ca>
To: Tom de Vries <tdevries@suse.de>, gdb-patches@sourceware.org
Subject: Re: [PATCH 3/7] [gdbsupport] Factor out base_next_iterator
Date: Thu, 30 Apr 2026 12:24:36 -0400 [thread overview]
Message-ID: <52ebd2ce-a27b-4cf6-81f4-ad3fa3537ee1@simark.ca> (raw)
In-Reply-To: <20260423063530.1074175-4-tdevries@suse.de>
On 4/23/26 2:35 AM, Tom de Vries wrote:
> diff --git a/gdbsupport/next-iterator.h b/gdbsupport/next-iterator.h
> index 0c90428d349..1dee941a252 100644
> --- a/gdbsupport/next-iterator.h
> +++ b/gdbsupport/next-iterator.h
> @@ -21,27 +21,43 @@
>
> #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. */
I'm of the opinion that this information is not really relevant here, it
belongs to the commit message.
I was initially skeptic that the version with the pointer-to-member
didn't work, so I tried it for myself and indeed, I don't think it would
work with the block and superblock_iterator relationship (at least, if
we want to have a method of block returning a
superblock_iterator/range).
While next_iterator is "iterate using the raw field `next`",
base_next_iterator is more generic just for "iterating over a field of a
type". It looks like you defined a pretty generic class where the
derived class only needs to fill in operator++ (and perhaps a bit more
boilerplate). But operator++ doesn't have to just follow a field, it
can have any logic in there, as function_block_iterator proves, which is
nice. Following the raw `next` field (or another raw field of any other
name) is just one specific case.
Given that all the concrete iterate needs to provide is "given a
reference to the current element, give me the next element", I think we
could reduce the boilerplate needed at each site by having the concrete
iterator provide a functor that does the increment (much like you
defined an std::map by providing a "hash" functor, not by deriving from
std::map).
Rather than copy paste what I mean here, I pushed what I think it could
look like to the users/simark/next-iterator branch.
https://sourceware.org/git/?p=binutils-gdb.git;a=shortlog;h=refs/heads/users/simark/next-iterator
https://sourceware.org/cgit/binutils-gdb/log/?h=users/simark/next-iterator
But just to illustrate here is how the function block iterator and
range are implemented:
/* Iterator and range type to iterate over this block and its superblocks
within a function. */
struct function_block_incrementer
{
const block *operator() (const block &b) const noexcept
{
/* If the current item is the function-defining block, we're done. */
if (b.function () != nullptr)
return nullptr;
return b.superblock ();
}
};
using function_block_iterator
= base_next_iterator<const block, function_block_incrementer>;
using function_block_range = iterator_range<function_block_iterator>;
I kept the name `base_next_iterator`, we could perhaps find a better
name, since it's not realted to `next_iterator` more than any other
concrete instance. Perhaps `base_iterator`, or `simple_iterator`?
> @@ -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;
I think we should use `using` instead of typedef everywhere now.
> +
> + explicit next_iterator (T *item)
> + : base_next_iterator<T> (item)
> {
> - m_item = m_item->next;
> - return *this;
> }
>
> -private:
> + next_iterator () = default;
Just noting that instead of those two constructors, you can use:
using base_next_iterator<T>::base_next_iterator;
Simon
next prev parent reply other threads:[~2026-04-30 16:25 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-23 6:35 [PATCH 0/7] [gdb] Add superblocks range loops Tom de Vries
2026-04-23 6:35 ` [PATCH 1/7] [gdb] Use block::function_block Tom de Vries
2026-04-23 14:33 ` Tom Tromey
2026-04-24 12:19 ` Tom de Vries
2026-04-23 6:35 ` [PATCH 2/7] [gdbsupport] Add parameterless iterator_range constructor Tom de Vries
2026-04-23 14:34 ` Tom Tromey
2026-04-24 12:20 ` Tom de Vries
2026-04-23 6:35 ` [PATCH 3/7] [gdbsupport] Factor out base_next_iterator Tom de Vries
2026-04-30 16:24 ` Simon Marchi [this message]
2026-04-30 19:09 ` Simon Marchi
2026-05-01 12:57 ` Tom Tromey
2026-05-01 13:20 ` Tom de Vries
2026-05-01 13:15 ` Tom de Vries
[not found] ` <87340kpbwx.fsf@tromey.com>
2026-04-30 4:49 ` Tom de Vries
2026-05-01 12:54 ` Tom de Vries
2026-05-01 13:00 ` Tom de Vries
2026-04-23 6:35 ` [PATCH 4/7] [gdb] Add block::superblocks Tom de Vries
2026-04-27 11:11 ` Jan Vrany
2026-05-01 13:06 ` Tom de Vries
2026-04-30 16:24 ` Simon Marchi
2026-05-01 13:19 ` Tom de Vries
2026-04-23 6:35 ` [PATCH 5/7] [gdb] Use block::super_blocks Tom de Vries
2026-04-24 16:27 ` Tom Tromey
2026-04-24 21:24 ` Tom de Vries
2026-04-23 6:35 ` [PATCH 6/7] [gdb] Add block::function_blocks Tom de Vries
2026-04-23 6:35 ` [PATCH 7/7] [gdb] Use block::function_blocks Tom de Vries
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52ebd2ce-a27b-4cf6-81f4-ad3fa3537ee1@simark.ca \
--to=simark@simark.ca \
--cc=gdb-patches@sourceware.org \
--cc=tdevries@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox