blob: 504d789f0ac36dc755b0919011050a64bb00ac7f [file]
/* 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 <http://www.gnu.org/licenses/>. */
#ifndef GDBSUPPORT_ENUMERATE_H
#define GDBSUPPORT_ENUMERATE_H
#include <cstddef>
#include <iterator>
#include <tuple>
#include <utility>
namespace gdb::ranges::views
{
/* An iterator that wraps another iterator and yields tuples containing
both the index and the value. */
template<typename Iterator>
class enumerate_iterator
{
using base_iterator = Iterator;
public:
using value_type
= std::tuple<std::size_t,
typename std::iterator_traits<base_iterator>::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<typename Range>
class enumerate_range
{
using base_iterator = decltype (std::begin (std::declval<Range &> ()));
public:
using iterator = enumerate_iterator<base_iterator>;
explicit enumerate_range (Range &&range)
: m_range (std::forward<Range> (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<int> 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<typename Range>
enumerate_range<Range>
enumerate (Range &&range)
{
return enumerate_range<Range> (std::forward<Range> (range));
}
} /* namespace gdb::ranges::views */
#endif /* GDBSUPPORT_ENUMERATE_H */