From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kqJaFbubtWmUXikAWB0awg (envelope-from ) for ; Sat, 14 Mar 2026 13:32:43 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=FJHf0sV6; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 4456F1E089; Sat, 14 Mar 2026 13:32:43 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 8AEAE1E089 for ; Sat, 14 Mar 2026 13:32:41 -0400 (EDT) Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id E78994C318B8 for ; Sat, 14 Mar 2026 17:32:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E78994C318B8 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=polymtl.ca header.i=@polymtl.ca header.a=rsa-sha256 header.s=oct2025 header.b=FJHf0sV6 Received: from smtp.polymtl.ca (smtp.polymtl.ca [132.207.4.11]) by sourceware.org (Postfix) with ESMTPS id 697FF4C3186B for ; Sat, 14 Mar 2026 17:32:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 697FF4C3186B Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=polymtl.ca Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=polymtl.ca ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 697FF4C3186B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=132.207.4.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773509532; cv=none; b=T8cAZR31MysrnkBGJN5kevumfraklO+89TKu7cCXkyGypWz3n+TTp35Utlu4lDroJ/N4n4PVLaumsxPh8DJh1cyXFZCLIWEof+ILWsJhJbNzDJqJH/bo1FNW6+4oJPt+EBEB+5gTWLf1+t3s4QIx0piGdOCrpQCiaPofTyCfXtA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1773509532; c=relaxed/simple; bh=EULGM0SdVgouwc5f2J/1trdZf52IrQ4By5VYhJVzQG4=; h=DKIM-Signature:Message-ID:Date:MIME-Version:Subject:To:From; b=lNxAfcqwkAPoixUS5C1fa5LCpcKxe9Y4W/SXmMTyNPwt9J+h+tlgN04QFXvubhPlA0X4gWUD+0I07vPdwUUFN520uKYtAbIN+NWYPztVuCz00z2sCWtyqP7qvG+xFyPbqmhdpQ9x9JvP+GGM3Zi8mBMJiCF7bThxob0p19s9HEg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 697FF4C3186B Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 62EHW7lW123210 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Sat, 14 Mar 2026 13:32:11 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 62EHW7lW123210 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=oct2025; t=1773509531; bh=z03iWmZqXfvrjZFlEnIC1EihYdMZTAbpVJgen3ijqvc=; h=Date:Subject:To:From:In-Reply-To:From; b=FJHf0sV6O3z/1XJCBvMNZ/o7qQmvJ2MU6YwpWFV47wyBzbjztfYJwgUpMVlhHADvj k0UxPKvJdZ8azZ4BiXaPg2v5hXLqMZfcMx5dX3UxaxJ1YbTF/hxIVTKpg+kg+jvXS9 mtBkhzhi3Y1qy+OEM3XwsRyUER9Zed/ZtCRAlhOTdMInIVo9OaTkYJbSjvGWYdInyf Ro4RfwAQY9RSYNcoZLnIjTLwDQq4BOUyscs3uG7/I8JZTIZb/Oad0B3DC0I7ifZISR /OwrFQt3eQ+yIoDVeWrgEvubK1atHwizjtN0/vjjRpJpc42QaFaCWDBazq4qCyBT/O zai69qElwt7LQ== Received: by simark.ca (Postfix) id B62451E089 for ; Sat, 14 Mar 2026 13:32:06 -0400 (EDT) Message-ID: <494266ff-61ff-4e68-936e-a387e543a73e@polymtl.ca> Date: Sat, 14 Mar 2026 13:32:06 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2 1/3] gdbsupport: add gdb::ranges::views::enumerate util To: gdb-patches@sourceware.org References: <20260220202002.860008-1-simon.marchi@efficios.com> <20260221011924.2029855-1-simon.marchi@polymtl.ca> Content-Language: en-US From: Simon Marchi In-Reply-To: <20260221011924.2029855-1-simon.marchi@polymtl.ca> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Sat, 14 Mar 2026 17:32:07 +0000 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Ping. On 2026-02-20 20:18, simon.marchi@polymtl.ca wrote: > From: Simon Marchi > > Add a "enumerate" utility, that acts pretty much like Python's > enumerate(). It makes the code slightly nicer, for when you would > otherwise need to handle the counter by hand. > > It can be used like this: > > std::vector my_vector; > for (auto [i, val] : gdb::ranges::views::enumerate (my_vector)) > ... > > `i` will hold the 0-based index of the current iteration, and `val` will > be a reference to the value of the current iteration. > > The name is chosen to match std::ranges::views::enumerate from C++23, > making it easy to switch to that eventually. > > Change-Id: I1870ab50537bcf54bba44a30a0b01ab397be16e3 > --- > gdb/Makefile.in | 1 + > gdb/unittests/enumerate-selftests.c | 154 ++++++++++++++++++++++++++++ > gdbsupport/enumerate.h | 121 ++++++++++++++++++++++ > 3 files changed, 276 insertions(+) > create mode 100644 gdb/unittests/enumerate-selftests.c > create mode 100644 gdbsupport/enumerate.h > > diff --git a/gdb/Makefile.in b/gdb/Makefile.in > index 2aa95be968ac..93701c962fed 100644 > --- a/gdb/Makefile.in > +++ b/gdb/Makefile.in > @@ -462,6 +462,7 @@ SELFTESTS_SRCS = \ > unittests/common-utils-selftests.c \ > unittests/copy_bitwise-selftests.c \ > unittests/enum-flags-selftests.c \ > + unittests/enumerate-selftests.c \ > unittests/environ-selftests.c \ > unittests/filtered_iterator-selftests.c \ > unittests/format_pieces-selftests.c \ > diff --git a/gdb/unittests/enumerate-selftests.c b/gdb/unittests/enumerate-selftests.c > new file mode 100644 > index 000000000000..ddda29f66251 > --- /dev/null > +++ b/gdb/unittests/enumerate-selftests.c > @@ -0,0 +1,154 @@ > +/* Self tests for the enumerate range adapter. > + > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#include "gdbsupport/selftest.h" > +#include "gdbsupport/enumerate.h" > + > +#include > +#include > + > +namespace selftests { > + > +static void > +test_enumerate () > +{ > + /* Test basic enumeration over a vector. */ > + { > + std::vector vec = { 10, 20, 30, 40 }; > + std::vector> result; > + std::vector> expected { > + {0, 10}, > + {1, 20}, > + {2, 30}, > + {3, 40} > + }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test enumeration over an std::array. */ > + { > + std::array arr = { 5, 6, 7 }; > + std::vector> result; > + std::vector> expected { > + {0, 5}, > + {1, 6}, > + {2, 7} > + }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (arr)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test enumeration over a C array. */ > + { > + int arr[] = { 8, 9, 10 }; > + std::vector> result; > + std::vector> expected { > + {0, 8}, > + {1, 9}, > + {2, 10} > + }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (arr)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test that enumeration allows modification of elements. */ > + { > + std::vector vec = { 1, 2, 3 }; > + std::vector expected = { 10, 20, 30 }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + val *= 10; > + > + SELF_CHECK (vec == expected); > + } > + > + /* Test enumeration over an empty container. */ > + { > + std::vector vec; > + std::vector> result; > + std::vector> expected; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test enumeration over a single-element container. */ > + { > + std::vector vec = { 42 }; > + std::vector> result; > + std::vector> expected { > + {0, 42} > + }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test enumeration over an rvalue container. */ > + { > + std::vector> result; > + std::vector> expected { > + {0, 17}, > + {1, 38}, > + {2, 99} > + }; > + > + for (auto [i, val] : > + gdb::ranges::views::enumerate (std::vector { 17, 38, 99 })) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > + > + /* Test enumeration with const container. */ > + { > + const std::vector vec = { 100, 200 }; > + std::vector> result; > + std::vector> expected { > + {0, 100}, > + {1, 200} > + }; > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + result.push_back ({ i, val }); > + > + SELF_CHECK (result == expected); > + } > +} > + > +} /* namespace selftests */ > + > +INIT_GDB_FILE (enumerate_selftests) > +{ > + selftests::register_test ("enumerate", selftests::test_enumerate); > +} > diff --git a/gdbsupport/enumerate.h b/gdbsupport/enumerate.h > new file mode 100644 > index 000000000000..504d789f0ac3 > --- /dev/null > +++ b/gdbsupport/enumerate.h > @@ -0,0 +1,121 @@ > +/* An enumerate range adapter for GDB, the GNU debugger. > + Copyright (C) 2026 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see . */ > + > +#ifndef GDBSUPPORT_ENUMERATE_H > +#define GDBSUPPORT_ENUMERATE_H > + > +#include > +#include > +#include > +#include > + > +namespace gdb::ranges::views > +{ > + > +/* An iterator that wraps another iterator and yields tuples containing > + both the index and the value. */ > + > +template > +class enumerate_iterator > +{ > + using base_iterator = Iterator; > +public: > + using value_type > + = std::tuple + typename std::iterator_traits::reference>; > + > + explicit enumerate_iterator (Iterator it) > + : m_it (std::move (it)) > + {} > + > + value_type operator* () const > + { return { m_index, *m_it }; } > + > + enumerate_iterator &operator++ () > + { > + ++m_it; > + ++m_index; > + return *this; > + } > + > + bool operator== (const enumerate_iterator &other) const > + { return m_it == other.m_it; } > + > + bool operator!= (const enumerate_iterator &other) const > + { return m_it != other.m_it; } > + > +private: > + Iterator m_it; > + std::size_t m_index = 0; > +}; > + > +/* A range adapter that allows iteration on both index and value. */ > + > +template > +class enumerate_range > +{ > + using base_iterator = decltype (std::begin (std::declval ())); > + > +public: > + using iterator = enumerate_iterator; > + > + explicit enumerate_range (Range &&range) > + : m_range (std::forward (range)) > + {} > + > + iterator begin () > + { return iterator (std::begin (m_range)); } > + > + iterator end () > + { return iterator (std::end (m_range)); } > + > +private: > + Range m_range; > +}; > + > +/* Return an enumerate_range for RANGE, allowing iteration with both > + index and value. > + > + Example usage: > + > + std::vector vec = {10, 20, 30}; > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + printf ("%zu: %d\n", i, val); > + > + This prints: > + > + 0: 10 > + 1: 20 > + 2: 30 > + > + The value is a reference to the element in the container, so > + modifications are possible: > + > + for (auto [i, val] : gdb::ranges::views::enumerate (vec)) > + val *= 2; */ > + > +template > +enumerate_range > +enumerate (Range &&range) > +{ > + return enumerate_range (std::forward (range)); > +} > + > +} /* namespace gdb::ranges::views */ > + > +#endif /* GDBSUPPORT_ENUMERATE_H */ > > base-commit: 3049829f1e6dd849e5d3ca71d633990f8d799ae6