mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-05 01:10:24 +00:00
There are actually a couple of issues here:
1. We are not properly perfect-forwarding the iterable to the Enumerator
member. We are using the class template as the constructor type, but
we would actually have to do something like this to achieve perfect
forwarding:
template <typname Iter = Iterable>
Enumerator(Iter&&)
2. The begin / end methods on Enumerator (although they return by const-
ref) are making copies during for-each loops. The compiler basically
generates this when we call enumerate:
for (auto it = Enumerator::begin(); it != Enumerator::end(); ++it)
The creation of `it` above actually creates a copy of the returned
Enumerator instance.
To avoid all of this, let's create an intermediate structure to act as
the enumerated iterator. This structure does not hold the iterable and
thus is fine to copy. We can then let the compiler handle forwarding
the iterable to the Enumerator.
Cherry-picked from:
0edcd19615
60 lines
1.1 KiB
C++
60 lines
1.1 KiB
C++
/*
|
|
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/StdLibExtras.h>
|
|
|
|
namespace AK {
|
|
|
|
namespace Detail {
|
|
|
|
template<typename Iterable>
|
|
struct Enumerator {
|
|
using IteratorType = decltype(declval<Iterable>().begin());
|
|
using ValueType = decltype(*declval<IteratorType>());
|
|
|
|
struct Enumeration {
|
|
size_t index { 0 };
|
|
ValueType value;
|
|
};
|
|
|
|
struct Iterator {
|
|
Enumeration operator*() { return { index, *iterator }; }
|
|
Enumeration operator*() const { return { index, *iterator }; }
|
|
|
|
bool operator!=(Iterator const& other) const { return iterator != other.iterator; }
|
|
|
|
void operator++()
|
|
{
|
|
++index;
|
|
++iterator;
|
|
}
|
|
|
|
size_t index { 0 };
|
|
IteratorType iterator;
|
|
};
|
|
|
|
Iterator begin() { return { 0, iterable.begin() }; }
|
|
Iterator end() { return { 0, iterable.end() }; }
|
|
|
|
Iterable iterable;
|
|
};
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
auto enumerate(T&& range)
|
|
{
|
|
return Detail::Enumerator<T> { forward<T>(range) };
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef USING_AK_GLOBALLY
|
|
using AK::enumerate;
|
|
#endif
|