/* * This file is part of the DXX-Rebirth project . * It is copyright by its individual contributors, as recorded in the * project's Git history. See COPYING.txt at the top level for license * terms and a link to the Git history. */ #pragma once #include #include "dxxsconf.h" #include "partial_range.h" /* * This could have been done using a std::pair, but using a custom type * allows for more descriptive member names. */ template struct enumerated_value { range_value_type &value; const index_type idx; }; template class enumerated_iterator { range_iterator_type m_iter; index_type m_idx; public: enumerated_iterator(const range_iterator_type &iter, const index_type idx) : m_iter(iter), m_idx(idx) { } result_type operator*() const { return {*m_iter, m_idx}; } enumerated_iterator &operator++() { ++ m_iter; ++ m_idx; return *this; } bool operator!=(const enumerated_iterator &i) const { return m_iter != i.m_iter; } }; template class enumerated_range : partial_range_t { using base_type = partial_range_t; using enumerated_iterator_type = enumerated_iterator()), index_type>>; const index_type m_idx; public: enumerated_range(const range_iterator_type b, const range_iterator_type e, const index_type i) : base_type(b, e), m_idx(i) { } template enumerated_range(range_type &t, const index_type i) : base_type(t), m_idx(i) { } enumerated_iterator_type begin() const { return enumerated_iterator_type(this->base_type::begin(), m_idx); } enumerated_iterator_type end() const { return enumerated_iterator_type(this->base_type::end(), 0 /* unused */); } }; template ()))> static enumerated_range enumerate(range_type &r, const index_type start = 0) { return enumerated_range(r, start); } /* * As a special case, allow rvalue reference to * partial_range_t, since partial_range_t does not * own the data over which it iterates, and so it does not need to * persist past the creation of the enumerated_range. * * This special case is legal for any temporary range which acts as a * view on a persistent sequence. */ template static enumerated_range enumerate(partial_range_t &&r, const index_type start = 0) { return enumerated_range(r, start); }