diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-08 15:47:50 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-10-08 15:47:50 +0200 |
commit | 78273d519c9251819758c0545973c89332942c6e (patch) | |
tree | 1fd016b5cac208b6a94b59c99715cab0780970fc | |
parent | 5c9eb51cc80a7bfc6ccf1e8cc6534a1e85efb1fe (diff) |
a
-rw-r--r-- | src/tile-iterator.hpp | 101 | ||||
-rw-r--r-- | test/tile-iter.cpp | 4 |
2 files changed, 58 insertions, 47 deletions
diff --git a/src/tile-iterator.hpp b/src/tile-iterator.hpp index 1bb8b7e6..09d41550 100644 --- a/src/tile-iterator.hpp +++ b/src/tile-iterator.hpp @@ -7,70 +7,77 @@ namespace Magnum::Examples { -template<typename T> class basic_tile_iterator; struct tile; +template<typename T> class basic_tile_iterator; +template<typename T> struct tile_tuple; } // namespace Magnum::Examples namespace std { -template<typename T> struct tuple_element<0, Magnum::Examples::basic_tile_iterator<T>> { using type = T&; }; -template<typename T> struct tuple_element<0, const Magnum::Examples::basic_tile_iterator<T>> { using type = const T&; }; -template<typename T> struct tuple_element<1, Magnum::Examples::basic_tile_iterator<T>> { using type = std::size_t; }; -template<typename T> struct tuple_element<2, Magnum::Examples::basic_tile_iterator<T>> { using type = Magnum::Examples::local_coords; }; -template<typename T> struct tuple_size<Magnum::Examples::basic_tile_iterator<T>> : std::integral_constant<std::size_t, 3> {}; +template<typename T> struct tuple_size<Magnum::Examples::tile_tuple<T>> : std::integral_constant<std::size_t, 3> {}; + +template<> struct tuple_element<0, Magnum::Examples::tile_tuple<Magnum::Examples::tile>> { using type = Magnum::Examples::tile&; }; +template<> struct tuple_element<0, Magnum::Examples::tile_tuple<const Magnum::Examples::tile>> { using type = const Magnum::Examples::tile&; }; +template<> struct tuple_element<0, const Magnum::Examples::tile_tuple<Magnum::Examples::tile>> { using type = const Magnum::Examples::tile&; }; + +template<typename T> struct tuple_element<1, Magnum::Examples::tile_tuple<T>> { using type = std::size_t; }; +template<typename T> struct tuple_element<2, Magnum::Examples::tile_tuple<T>> { using type = Magnum::Examples::local_coords; }; } // namespace std namespace Magnum::Examples { template<typename T> -class basic_tile_iterator final { - T* ptr; - std::size_t pos = 0; +struct tile_tuple { + tile_tuple(T* ptr, std::size_t pos) : data{ptr, pos} {} + tile_tuple(const tile_tuple<T>&) = default; + tile_tuple<T>& operator=(const tile_tuple<T>&) = default; + + template <std::size_t N> + typename std::tuple_element<N, tile_tuple<T>>::type get() + { + auto& [ptr, pos] = data; + 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<std::integral_constant<int, N>>(); + } + + template <std::size_t N> + typename std::tuple_element<N, const tile_tuple<const T>>::type get() const { + return const_cast<tile_tuple<T>&>(*this).get<N>(); + } + + auto operator<=>(const tile_tuple<T>&) const noexcept = default; + +protected: + std::tuple<T*, std::size_t> data = {nullptr, 0}; +}; -public: - explicit basic_tile_iterator(T* ptr, std::size_t pos) noexcept : ptr(ptr), pos(pos) {} - ~basic_tile_iterator() noexcept = default; +} // namespace Magnum::Examples + +namespace Magnum::Examples { +template<typename T> +class basic_tile_iterator final : private tile_tuple<T> { +public: + explicit basic_tile_iterator(T* ptr, std::size_t pos) noexcept : tile_tuple<T>{ptr, pos} {} + basic_tile_iterator(const basic_tile_iterator&) = default; basic_tile_iterator<T>& operator=(const basic_tile_iterator<T>&) = default; - basic_tile_iterator<T>& operator++() { pos++; return *this; } - basic_tile_iterator<T> operator++(int) { auto tmp = *this; operator++(); return tmp; } - basic_tile_iterator<T>& operator*() { return *this; } + auto operator<=>(const basic_tile_iterator<T>&) const noexcept = default; - void swap(basic_tile_iterator<T>& other); - template<std::size_t N> typename std::tuple_element<N, basic_tile_iterator<T>>::type get() &; - template<std::size_t N> typename std::tuple_element<N, basic_tile_iterator<T>>::type get() const&; -}; + void swap(basic_tile_iterator<T>& other) { std::swap(this->data, other.data); } -template <typename T> -void basic_tile_iterator<T>::swap(basic_tile_iterator<T>& other) -{ - using std::swap; - swap(ptr, other.ptr); - swap(pos, other.pos); -} - -template <typename T> -template <std::size_t N> -typename std::tuple_element<N, basic_tile_iterator<T>>::type basic_tile_iterator<T>::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<std::integral_constant<int, N>>(); -} - -template <typename T> -template <std::size_t N> -typename std::tuple_element<N, basic_tile_iterator<T>>::type basic_tile_iterator<T>::get() const& -{ - return const_cast<basic_tile_iterator<T>&>(*this).get<N>(); -} + basic_tile_iterator<T>& operator++() { auto& [ptr, pos] = this->data; pos++; return *this; } + basic_tile_iterator<T> operator++(int) { auto tmp = *this; operator++(); return tmp; } + tile_tuple<T>* operator->() { return this; } + tile_tuple<T>& operator*() { return *this; } +}; extern template class basic_tile_iterator<tile>; extern template class basic_tile_iterator<const tile>; diff --git a/test/tile-iter.cpp b/test/tile-iter.cpp index a6a5db8a..360b2319 100644 --- a/test/tile-iter.cpp +++ b/test/tile-iter.cpp @@ -31,11 +31,15 @@ bool app::test_tile_iter() // NOLINT(readability-function-size) static_assert(std::is_same_v<decltype(x), const tile&>); for (auto [x, k, pt] : c) static_assert(std::is_same_v<decltype(x), tile&>); +#if 0 + // warns for (const auto [x, k, pt] : c) static_assert(std::is_same_v<decltype(x), const tile&>); +#endif for (auto&& [x, k, pt] : c) static_assert(std::is_same_v<decltype(x), tile&>); #if 0 + // fails to compile for (const auto&& [x, k, pt] : c) static_assert(std::is_same_v<decltype(x), const tile&>); #endif |