/* * Copyright (c) 2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include namespace AK { namespace Detail { template class Enumerator { using IteratorType = decltype(declval().begin()); using ValueType = decltype(*declval()); struct Enumeration { size_t index { 0 }; ValueType value; }; public: Enumerator(Iterable&& iterable) : m_iterable(forward(iterable)) , m_iterator(m_iterable.begin()) , m_end(m_iterable.end()) { } Enumerator const& begin() const { return *this; } Enumerator const& end() const { return *this; } Enumeration operator*() { return { m_index, *m_iterator }; } Enumeration operator*() const { return { m_index, *m_iterator }; } bool operator!=(Enumerator const&) const { return m_iterator != m_end; } void operator++() { ++m_index; ++m_iterator; } private: Iterable m_iterable; size_t m_index { 0 }; IteratorType m_iterator; IteratorType const m_end; }; } template auto enumerate(T&& range) { return Detail::Enumerator { forward(range) }; } } #ifdef USING_AK_GLOBALLY using AK::enumerate; #endif