#pragma once #include "local-coords.hpp" #include "tile.hpp" #include #include #include #include namespace Magnum::Examples { template class basic_tile_iterator; struct tile; } // namespace Magnum::Examples namespace std { template constexpr void swap(Magnum::Examples::basic_tile_iterator& lhs, Magnum::Examples::basic_tile_iterator& rhs) noexcept; } // namespace std namespace Magnum::Examples { namespace detail { template class tile_tuple_wrapper final { using value_type = std::tuple; value_type value; public: constexpr tile_tuple_wrapper(value_type x) : value(x) {} constexpr value_type& operator*() noexcept { return value; } constexpr value_type* operator->() noexcept { return &value; } }; } // namespace detail template class basic_tile_iterator final { T* ptr; std::size_t pos = 0; friend constexpr void swap(basic_tile_iterator& lhs, basic_tile_iterator& rhs) noexcept; public: using value_type = std::tuple; explicit constexpr basic_tile_iterator(T* ptr, std::size_t pos) noexcept : ptr(ptr), pos(pos) {} constexpr ~basic_tile_iterator() noexcept = default; constexpr basic_tile_iterator& operator=(const basic_tile_iterator&) noexcept = default; constexpr basic_tile_iterator& operator++() noexcept { pos++; return *this; } constexpr basic_tile_iterator operator++(int) noexcept { auto tmp = *this; operator++(); return tmp; } constexpr value_type operator*() const noexcept { // NOLINT(bugprone-exception-escape) ASSERT(pos < TILE_COUNT); return {ptr[pos], pos, local_coords{pos}}; } constexpr detail::tile_tuple_wrapper operator->() const noexcept { // NOLINT(bugprone-exception-escape) return {operator*()}; } constexpr auto operator<=>(const basic_tile_iterator&) const noexcept = default; }; template constexpr void swap(basic_tile_iterator& lhs, basic_tile_iterator& rhs) noexcept { using std::swap; swap(lhs.ptr, rhs.ptr); swap(lhs.pos, rhs.ptr); } 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