#pragma once #include #include #include namespace BAN { template constexpr It next(It it, size_t count) { for (size_t i = 0; i < count; i++) ++it; return it; } template requires requires(It it, size_t n) { requires is_same_v; } constexpr It next(It it, size_t count) { return it + count; } template constexpr It prev(It it, size_t count) { for (size_t i = 0; i < count; i++) --it; return it; } template requires requires(It it, size_t n) { requires is_same_v; } constexpr It prev(It it, size_t count) { return it - count; } template constexpr size_t distance(It it1, It it2) { size_t dist = 0; while (it1 != it2) { ++it1; ++dist; } return dist; } template requires requires(It it1, It it2) { requires is_integral_v; } constexpr size_t distance(It it1, It it2) { return it2 - it1; } template class IteratorSimpleGeneral { public: using value_type = T; public: constexpr IteratorSimpleGeneral() = default; template> constexpr IteratorSimpleGeneral(const IteratorSimpleGeneral& other) : m_pointer(other.m_pointer) , m_valid(other.m_valid) { } constexpr const T& operator*() const { ASSERT(m_pointer); return *m_pointer; } template constexpr enable_if_t operator*() { ASSERT(*this); ASSERT(m_pointer); return *m_pointer; } constexpr const T* operator->() const { ASSERT(*this); ASSERT(m_pointer); return m_pointer; } template constexpr enable_if_t operator->() { ASSERT(*this); ASSERT(m_pointer); return m_pointer; } constexpr IteratorSimpleGeneral& operator++() { ASSERT(*this); ASSERT(m_pointer); ++m_pointer; return *this; } constexpr IteratorSimpleGeneral operator++(int) { auto temp = *this; ++(*this); return temp; } constexpr IteratorSimpleGeneral& operator--() { ASSERT(*this); ASSERT(m_pointer); --m_pointer; return *this; } constexpr IteratorSimpleGeneral operator--(int) { auto temp = *this; --(*this); return temp; } constexpr size_t operator-(const IteratorSimpleGeneral& other) const { ASSERT(*this && other); return m_pointer - other.m_pointer; } constexpr IteratorSimpleGeneral operator+(size_t offset) const { return IteratorSimpleGeneral(m_pointer + offset); } constexpr IteratorSimpleGeneral operator-(size_t offset) const { return IteratorSimpleGeneral(m_pointer - offset); } constexpr bool operator<(const IteratorSimpleGeneral& other) const { ASSERT(*this); return m_pointer < other.m_pointer; } constexpr bool operator==(const IteratorSimpleGeneral& other) const { ASSERT(*this); return m_pointer == other.m_pointer; } constexpr bool operator!=(const IteratorSimpleGeneral& other) const { ASSERT(*this); return !(*this == other); } constexpr explicit operator bool() const { return m_valid; } private: constexpr IteratorSimpleGeneral(maybe_const_t* pointer) : m_pointer(pointer) , m_valid(true) { } private: maybe_const_t* m_pointer = nullptr; bool m_valid = false; friend IteratorSimpleGeneral; friend Container; }; template typename OuterContainer, template typename InnerContainer, typename Container, bool CONST> class IteratorDoubleGeneral { public: using Inner = InnerContainer; using Outer = OuterContainer; using InnerIterator = either_or_t; using OuterIterator = either_or_t; using value_type = T; public: constexpr IteratorDoubleGeneral() = default; template> constexpr IteratorDoubleGeneral(const IteratorDoubleGeneral& other) : m_outer_end(other.m_outer_end) , m_outer_current(other.m_outer_current) , m_inner_current(other.m_inner_current) { } constexpr const T& operator*() const { ASSERT(*this); ASSERT(m_outer_current != m_outer_end); ASSERT(m_inner_current); return m_inner_current.operator*(); } template constexpr enable_if_t operator*() { ASSERT(*this); ASSERT(m_outer_current != m_outer_end); ASSERT(m_inner_current); return m_inner_current.operator*(); } constexpr const T* operator->() const { ASSERT(*this); ASSERT(m_outer_current != m_outer_end); ASSERT(m_inner_current); return m_inner_current.operator->(); } template constexpr enable_if_t operator->() { ASSERT(*this); ASSERT(m_outer_current != m_outer_end); ASSERT(m_inner_current); return m_inner_current.operator->(); } constexpr IteratorDoubleGeneral& operator++() { ASSERT(*this); ASSERT(m_outer_current != m_outer_end); ASSERT(m_inner_current); m_inner_current++; find_valid_or_end(); return *this; } constexpr IteratorDoubleGeneral operator++(int) { auto temp = *this; ++(*this); return temp; } constexpr bool operator==(const IteratorDoubleGeneral& other) const { ASSERT(*this && other); if (m_outer_end != other.m_outer_end) return false; if (m_outer_current != other.m_outer_current) return false; if (m_outer_current == m_outer_end) return true; ASSERT(m_inner_current && other.m_inner_current); return m_inner_current == other.m_inner_current; } constexpr bool operator!=(const IteratorDoubleGeneral& other) const { return !(*this == other); } constexpr explicit operator bool() const { return !!m_outer_current; } private: constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current) : m_outer_end(outer_end) , m_outer_current(outer_current) { if (outer_current != outer_end) { m_inner_current = m_outer_current->begin(); find_valid_or_end(); } } constexpr IteratorDoubleGeneral(const OuterIterator& outer_end, const OuterIterator& outer_current, const InnerIterator& inner_current) : m_outer_end(outer_end) , m_outer_current(outer_current) , m_inner_current(inner_current) { find_valid_or_end(); } constexpr void find_valid_or_end() { while (m_inner_current == m_outer_current->end()) { m_outer_current++; if (m_outer_current == m_outer_end) break; m_inner_current = m_outer_current->begin(); } } constexpr OuterIterator outer_current() { return m_outer_current; } constexpr InnerIterator inner_current() { return m_inner_current; } private: OuterIterator m_outer_end; OuterIterator m_outer_current; InnerIterator m_inner_current; friend class IteratorDoubleGeneral; friend Container; }; template using IteratorSimple = IteratorSimpleGeneral; template using ConstIteratorSimple = IteratorSimpleGeneral; template typename OuterContainer, template typename InnerContainer, typename Container> using IteratorDouble = IteratorDoubleGeneral; template typename OuterContainer, template typename InnerContainer, typename Container> using ConstIteratorDouble = IteratorDoubleGeneral; }