diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-15 09:19:04 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-15 11:30:21 +0100 |
commit | 79ee48e0f68a3c2db2e75615cf26d4c7a239744a (patch) | |
tree | 27a86c783306f993e5b0b878b3b11b266eca2fb4 | |
parent | 9584feecdd70f66e037e98f6386edcb342cb85c7 (diff) |
entity: add visit_tuple
-rw-r--r-- | src/entity.hpp | 27 | ||||
-rw-r--r-- | test/entity.cpp | 9 |
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; } |