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 11:30:21 +0100
commit79ee48e0f68a3c2db2e75615cf26d4c7a239744a (patch)
tree27a86c783306f993e5b0b878b3b11b266eca2fb4
parent9584feecdd70f66e037e98f6386edcb342cb85c7 (diff)
entity: add visit_tuple
-rw-r--r--src/entity.hpp27
-rw-r--r--test/entity.cpp9
2 files changed, 33 insertions, 3 deletions
diff --git a/src/entity.hpp b/src/entity.hpp
index 32ab759f..31a13632 100644
--- a/src/entity.hpp
+++ b/src/entity.hpp
@@ -131,11 +131,12 @@ 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>>;
+ using Size = std::tuple_size<std::remove_cvref_t<Tuple>>;
static_assert(N < Size());
fun(std::get<N>(tuple));
@@ -143,6 +144,20 @@ constexpr CORRADE_ALWAYS_INLINE void visit_tuple(F&& fun, Tuple&& tuple)
visit_tuple<F, Tuple, N+1>(std::forward<F>(fun), std::forward<Tuple>(tuple));
}
+template<typename F, typename Tuple, std::size_t N>
+requires std::is_invocable_r_v<bool, F, decltype(std::get<N>(std::declval<Tuple>()))>
+constexpr CORRADE_ALWAYS_INLINE bool find_in_tuple(F&& fun, Tuple&& tuple)
+{
+ using Size = std::tuple_size<std::remove_cvref_t<Tuple>>;
+ static_assert(N < Size());
+
+ if (fun(std::get<N>(tuple)))
+ return true;
+ if constexpr(N+1 < Size())
+ return find_in_tuple<F, Tuple, N+1>(std::forward<F>(fun), std::forward<Tuple>(tuple));
+ return false;
+}
+
} // namespace detail
template<typename F, typename Tuple>
@@ -153,6 +168,16 @@ constexpr void visit_tuple(F&& fun, Tuple&& tuple)
detail::visit_tuple<F, Tuple, 0>(std::forward<F>(fun), std::forward<Tuple>(tuple));
}
+template<typename F, typename Tuple>
+constexpr bool find_in_tuple(F&& fun, Tuple&& tuple)
+{
+ using Size = std::tuple_size<std::decay_t<Tuple>>;
+ if constexpr(Size() > 0)
+ return detail::find_in_tuple<F, Tuple, 0>(std::forward<F>(fun), std::forward<Tuple>(tuple));
+ else
+ return false;
+}
+
enum class erased_field_type : std::uint32_t {
none,
string,
diff --git a/test/entity.cpp b/test/entity.cpp
index 312fb18a..8266ec47 100644
--- a/test/entity.cpp
+++ b/test/entity.cpp
@@ -45,9 +45,9 @@ static constexpr bool test_accessors()
static constexpr bool test_visitor()
{
{
+ constexpr auto tuple = std::make_tuple((unsigned char)1, (unsigned short)2, (int)3, (long)4);
long ret = 0;
- visit_tuple([&](auto x) { ret += (long)x; },
- std::make_tuple((unsigned char)1, (unsigned short)2, (int)3, (long)4));
+ visit_tuple([&](auto x) { ret += (long)x; }, tuple);
fm_assert(ret == 1 + 2 + 3 + 4);
}
{
@@ -55,6 +55,11 @@ static constexpr bool test_visitor()
visit_tuple([&] { ret++; }, std::tuple<>{});
fm_assert(ret == 0);
}
+ {
+ constexpr auto tuple = std::make_tuple((char)1, (short)2, (long)3);
+ static_assert(find_in_tuple([](auto x) { return x == 3; }, tuple));
+ static_assert(!find_in_tuple([](auto x) { return x == 5; }, tuple));
+ }
return true;
}