summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-10-08 15:47:50 +0200
committerStanislaw Halik <sthalik@misaki.pl>2022-10-08 15:47:50 +0200
commit78273d519c9251819758c0545973c89332942c6e (patch)
tree1fd016b5cac208b6a94b59c99715cab0780970fc
parent5c9eb51cc80a7bfc6ccf1e8cc6534a1e85efb1fe (diff)
a
-rw-r--r--src/tile-iterator.hpp101
-rw-r--r--test/tile-iter.cpp4
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