#pragma once #include "local-coords.hpp" #include #include #include #include namespace floormat { struct tile; template class basic_tile_iterator; template struct tile_tuple; } // namespace floormat namespace std { template struct tuple_size> : std::integral_constant {}; template<> struct tuple_element<0, floormat::tile_tuple> { using type = floormat::tile&; }; template<> struct tuple_element<0, floormat::tile_tuple> { using type = const floormat::tile&; }; template<> struct tuple_element<0, const floormat::tile_tuple> { using type = const floormat::tile&; }; template struct tuple_element<1, floormat::tile_tuple> { using type = std::size_t; }; template struct tuple_element<2, floormat::tile_tuple> { using type = floormat::local_coords; }; } // namespace std namespace floormat { template struct tile_tuple { tile_tuple(T* ptr, std::size_t pos) : data{ptr, pos} {} tile_tuple(const tile_tuple&) = default; tile_tuple& operator=(const tile_tuple&) = default; template typename std::tuple_element>::type get() { auto& [ptr, pos] = data; if constexpr(N == 0) return ptr[pos]; else if constexpr(N == 1) return pos; else if constexpr(N == 2) return local_coords{pos}; else return std::void_t>(); } template typename std::tuple_element>::type get() const { return const_cast&>(*this).get(); } auto operator<=>(const tile_tuple&) const noexcept = default; protected: std::tuple data = {nullptr, 0}; }; } // namespace floormat namespace floormat { template class basic_tile_iterator final : private tile_tuple { public: explicit basic_tile_iterator(T* ptr, std::size_t pos) noexcept : tile_tuple{ptr, pos} {} basic_tile_iterator(const basic_tile_iterator&) = default; basic_tile_iterator& operator=(const basic_tile_iterator&) = default; auto operator<=>(const basic_tile_iterator&) const noexcept = default; void swap(basic_tile_iterator& other) { std::swap(this->data, other.data); } basic_tile_iterator& operator++() { auto& [ptr, pos] = this->data; pos++; return *this; } basic_tile_iterator operator++(int) { auto tmp = *this; operator++(); return tmp; } tile_tuple* operator->() { return this; } tile_tuple& operator*() { return *this; } }; extern template class basic_tile_iterator; extern template class basic_tile_iterator; } // namespace floormat namespace std { template class iterator_traits> { using T = floormat::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