From 604b4ae5720836cb4ee9a66085d3290067c63c84 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Tue, 15 Nov 2022 09:19:04 +0100 Subject: entity: add visit_tuple --- src/entity.hpp | 26 +++++++++++++++++++++++++- test/entity.cpp | 28 ++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/entity.hpp b/src/entity.hpp index 1c055ce7..ba165662 100644 --- a/src/entity.hpp +++ b/src/entity.hpp @@ -1,9 +1,10 @@ #pragma once #include "compat/integer-types.hpp" -#include #include #include #include +#include +#include namespace floormat {} @@ -128,6 +129,29 @@ struct Entity final { }; }; +namespace detail { +template +requires std::invocable(std::declval()))> +constexpr CORRADE_ALWAYS_INLINE void visit_tuple(F&& fun, Tuple&& tuple) +{ + using Size = std::tuple_size>; + static_assert(N < Size()); + + fun(std::get(tuple)); + if constexpr(N+1 < Size()) + visit_tuple(std::forward(fun), std::forward(tuple)); +} + +} // namespace detail + +template +constexpr void visit_tuple(F&& fun, Tuple&& tuple) +{ + using Size = std::tuple_size>; + if constexpr(Size() > 0) + detail::visit_tuple(std::forward(fun), std::forward(tuple)); +} + enum class erased_field_type : std::uint32_t { none, string, diff --git a/test/entity.cpp b/test/entity.cpp index 80032b6f..21783e24 100644 --- a/test/entity.cpp +++ b/test/entity.cpp @@ -1,13 +1,14 @@ #include "app.hpp" #include "compat/assert.hpp" #include "src/entity.hpp" +#include using namespace floormat; using namespace floormat::entities; struct TestAccessors { - int bar() const { return _bar; } - void set_bar(int value) { _bar = value; } + constexpr int bar() const { return _bar; } + constexpr void set_bar(int value) { _bar = value; } int foo; int _bar; int _baz; @@ -22,7 +23,7 @@ static constexpr auto m_baz = entity::type::field("baz"_s, r_baz, w_baz); namespace floormat { -static void test_accessors() +static constexpr bool test_accessors() { auto x = TestAccessors{111, 222, 333}; @@ -38,11 +39,30 @@ static void test_accessors() auto a = m_foo.read(x), b = m_bar.read(x), c = m_baz.read(x); fm_assert(a == 1111 && b == 2222 && c == 3333); } + return true; +} + +static constexpr bool test_visitor() +{ + { + int ret = 0; + visit_tuple([&](auto x) { ret += x; }, + std::tuple{ 1, 2, 3, 4 }); + fm_assert(ret == 1 + 2 + 3 + 4); + } + { + int ret = 0; + visit_tuple([&] { ret++; }, std::tuple<>{}); + fm_assert(ret == 0); + } + + return true; } void test_app::test_entity() { - test_accessors(); + static_assert(test_accessors()); + static_assert(test_visitor()); } } // namespace floormat -- cgit v1.2.3