#pragma once #include "local-coords.hpp" #include #include #include namespace Magnum::Examples { template class basic_tile_iterator; struct tile; } // namespace Magnum::Examples namespace std { template void swap(Magnum::Examples::basic_tile_iterator& lhs, Magnum::Examples::basic_tile_iterator& rhs) noexcept; template struct tuple_element<0, Magnum::Examples::basic_tile_iterator> { using type = T&; }; template struct tuple_element<0, const Magnum::Examples::basic_tile_iterator> { using type = const T&; }; template struct tuple_element<1, Magnum::Examples::basic_tile_iterator> { using type = std::size_t; }; template struct tuple_element<2, Magnum::Examples::basic_tile_iterator> { using type = Magnum::Examples::local_coords; }; template struct tuple_size> : std::integral_constant {}; } // namespace std namespace Magnum::Examples { template class basic_tile_iterator final { T* ptr; std::size_t pos = 0; public: using value_type = std::tuple; explicit basic_tile_iterator(T* ptr, std::size_t pos) noexcept : ptr(ptr), pos(pos) {} ~basic_tile_iterator() noexcept = default; basic_tile_iterator& operator=(const basic_tile_iterator&) = default; basic_tile_iterator& operator++() { pos++; return *this; } basic_tile_iterator operator++(int) { auto tmp = *this; operator++(); return tmp; } basic_tile_iterator* operator->() & { return this; } basic_tile_iterator& operator*() & { return *this; } basic_tile_iterator const* operator->() const& { return this; } basic_tile_iterator const& operator*() const& { return *this; } auto operator<=>(const basic_tile_iterator&) const noexcept = default; void swap(basic_tile_iterator& other); template typename std::tuple_element>::type get() &; template typename std::tuple_element>::type get() const&; }; template void basic_tile_iterator::swap(basic_tile_iterator& other) { using std::swap; swap(ptr, other.ptr); swap(pos, other.pos); } template template typename std::tuple_element>::type basic_tile_iterator::get() & { if constexpr(N == 0) return pos == TILE_COUNT ? ptr[0] : ptr[pos]; else if constexpr(N == 1) return pos; else if constexpr(N == 2) return local_coords{pos}; else return std::void_t>(); } template template typename std::tuple_element>::type basic_tile_iterator::get() const& { return const_cast&>(*this).get(); } extern template class basic_tile_iterator; extern template class basic_tile_iterator; } // namespace Magnum::Examples namespace std { template class iterator_traits> { using T = Magnum::Examples::basic_tile_iterator; public: using difference_type = std::ptrdiff_t; using value_type = T; using reference = T&; using pointer = T*; using iterator_category = std::input_iterator_tag; //usually std::forward_iterator_tag or similar }; } // namespace std