diff --git a/AK/Enumerate.h b/AK/Enumerate.h index d824605e7dd..0203f9b3dcf 100644 --- a/AK/Enumerate.h +++ b/AK/Enumerate.h @@ -11,8 +11,9 @@ namespace AK { namespace Detail { + template -class Enumerator { +struct Enumerator { using IteratorType = decltype(declval().begin()); using ValueType = decltype(*declval()); @@ -21,35 +22,28 @@ class Enumerator { ValueType value; }; -public: - Enumerator(Iterable&& iterable) - : m_iterable(forward(iterable)) - , m_iterator(m_iterable.begin()) - , m_end(m_iterable.end()) - { - } + struct Iterator { + Enumeration operator*() { return { index, *iterator }; } + Enumeration operator*() const { return { index, *iterator }; } - Enumerator const& begin() const { return *this; } - Enumerator const& end() const { return *this; } + bool operator!=(Iterator const& other) const { return iterator != other.iterator; } - Enumeration operator*() { return { m_index, *m_iterator }; } - Enumeration operator*() const { return { m_index, *m_iterator }; } + void operator++() + { + ++index; + ++iterator; + } - bool operator!=(Enumerator const&) const { return m_iterator != m_end; } + size_t index { 0 }; + IteratorType iterator; + }; - void operator++() - { - ++m_index; - ++m_iterator; - } + Iterator begin() { return { 0, iterable.begin() }; } + Iterator end() { return { 0, iterable.end() }; } -private: - Iterable m_iterable; - - size_t m_index { 0 }; - IteratorType m_iterator; - IteratorType const m_end; + Iterable iterable; }; + } template diff --git a/Tests/AK/TestEnumerate.cpp b/Tests/AK/TestEnumerate.cpp index dffc2869b62..728962aeab1 100644 --- a/Tests/AK/TestEnumerate.cpp +++ b/Tests/AK/TestEnumerate.cpp @@ -49,3 +49,43 @@ TEST_CASE(enumerate) EXPECT_EQ(result, (Vector { { 0, 9 }, { 1, 8 }, { 2, 7 }, { 3, 6 } })); } } + +class CopyCounter { +public: + static inline size_t copy_count = 0; + + CopyCounter() = default; + CopyCounter(CopyCounter const&) { ++copy_count; } + CopyCounter(CopyCounter&&) { } + + auto begin() const { return m_vec.begin(); } + auto end() const { return m_vec.end(); } + +private: + Vector m_vec { 1, 2, 3, 4 }; +}; + +TEST_CASE(do_not_copy) +{ + { + Vector result; + CopyCounter::copy_count = 0; + CopyCounter counter {}; + + for (auto [i, value] : enumerate(counter)) + result.append({ i, value }); + + EXPECT_EQ(result, (Vector { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 } })); + EXPECT_EQ(CopyCounter::copy_count, 0uz); + } + { + Vector result; + CopyCounter::copy_count = 0; + + for (auto [i, value] : enumerate(CopyCounter {})) + result.append({ i, value }); + + EXPECT_EQ(result, (Vector { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 } })); + EXPECT_EQ(CopyCounter::copy_count, 0uz); + } +}