#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_size> : std::integral_constant {}; template struct tuple_element<0, Magnum::Examples::basic_tile_iterator> { using type = 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; }; } // 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; } auto operator<=>(const basic_tile_iterator&) const noexcept = default; void swap(basic_tile_iterator& other) { using std::swap; swap(ptr, other.ptr); swap(pos, other.pos); } template typename std::tuple_element>::type 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>(); } }; extern template class basic_tile_iterator; extern template class basic_tile_iterator; } // namespace Magnum::Examples namespace std { template class iterator_traits> { using T = typename Magnum::Examples::basic_tile_iterator::value_type; 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