summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-15 09:19:04 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-15 09:53:30 +0100
commit604b4ae5720836cb4ee9a66085d3290067c63c84 (patch)
tree0865d470b757eb456929e045c1b45e9c8bad9c09
parent181bf16539d425d4f07501905cc9326b434ce75e (diff)
entity: add visit_tuple
-rw-r--r--src/entity.hpp26
-rw-r--r--test/entity.cpp28
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 <Corrade/Containers/StringView.h>
#include <concepts>
#include <compare>
#include <type_traits>
+#include <utility>
+#include <Corrade/Containers/StringView.h>
namespace floormat {}
@@ -128,6 +129,29 @@ struct Entity final {
};
};
+namespace detail {
+template<typename F, typename Tuple, std::size_t N>
+requires std::invocable<F, decltype(std::get<N>(std::declval<Tuple>()))>
+constexpr CORRADE_ALWAYS_INLINE void visit_tuple(F&& fun, Tuple&& tuple)
+{
+ using Size = std::tuple_size<std::decay_t<Tuple>>;
+ static_assert(N < Size());
+
+ fun(std::get<N>(tuple));
+ if constexpr(N+1 < Size())
+ visit_tuple<F, Tuple, N+1>(std::forward<F>(fun), std::forward<Tuple>(tuple));
+}
+
+} // namespace detail
+
+template<typename F, typename Tuple>
+constexpr void visit_tuple(F&& fun, Tuple&& tuple)
+{
+ using Size = std::tuple_size<std::decay_t<Tuple>>;
+ if constexpr(Size() > 0)
+ detail::visit_tuple<F, Tuple, 0>(std::forward<F>(fun), std::forward<Tuple>(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 <tuple>
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<int>::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<int, short, char, long>{ 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