From 520ccfcd06dba93c74654701a0fdd575fa6724f9 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sat, 19 Oct 2019 16:09:03 +0200 Subject: [PATCH] meta: support tuple as properties --- docs/md/meta.md | 16 +++++++++++++--- src/entt/meta/factory.hpp | 34 ++++++++++++++++++++++------------ test/entt/meta/meta.cpp | 5 ++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/docs/md/meta.md b/docs/md/meta.md index e2b538815..8cec68419 100644 --- a/docs/md/meta.md +++ b/docs/md/meta.md @@ -509,9 +509,19 @@ Furthermore, the `prop` function supports different formats for properties: entt::meta().type("reflected_type"_hs).prop(my_enum::key_only); ``` -In any case, one property can be associated at a time. However, it's possible to -invoke the `prop` function several times, one for each property to associate -with the last meta object created: +* Properties as `std::tuple`s: + + ```cpp + entt::meta().type("reflected_type"_hs) + .prop(std::make_tuple(std::make_pair("tooltip"_hs, "message"), my_enum::key_only)); + ``` + + A tuple can contain one or more properties expressed as described above, + except for the key/value form. It will be unpacked and the properties will be + treated individually. + +It's possible to invoke the `prop` function several times if needed, one for +each property to associate with the last meta object created: ```cpp entt::meta() diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index 51aeaa012..1acd2e60a 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -35,7 +35,7 @@ struct meta_function_helper { using return_type = std::remove_cv_t>; using args_type = std::tuple>...>; - static constexpr auto size = sizeof...(Args); + static constexpr std::index_sequence_for index_sequence{}; static constexpr auto is_const = false; static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT { @@ -415,10 +415,10 @@ public: type, nullptr, nullptr, - helper_type::size, + helper_type::index_sequence.size(), &helper_type::arg, [](meta_any * const any) { - return internal::invoke({}, any, std::make_index_sequence{}); + return internal::invoke({}, any, helper_type::index_sequence); } }; @@ -448,10 +448,10 @@ public: type, nullptr, nullptr, - helper_type::size, + helper_type::index_sequence.size(), &helper_type::arg, [](meta_any * const any) { - return internal::construct>...>(any, std::make_index_sequence{}); + return internal::construct>...>(any, helper_type::index_sequence); } }; @@ -650,13 +650,13 @@ public: type, nullptr, nullptr, - helper_type::size, + helper_type::index_sequence.size(), helper_type::is_const, !std::is_member_function_pointer_v, &internal::meta_info, void, typename helper_type::return_type>>::resolve, &helper_type::arg, [](meta_handle handle, meta_any *any) { - return internal::invoke(handle, any, std::make_index_sequence{}); + return internal::invoke(handle, any, helper_type::index_sequence); } }; @@ -696,13 +696,23 @@ class extended_meta_factory: public meta_factory { return node && (node->key() == key || duplicate(key, node->next)); } + template + void unpack(std::tuple property, std::index_sequence) { + (unpack(choice<2>, std::get(property)), ...); + } + template - void unpack(int, std::pair property) { - unpack(0, std::get<0>(property), std::get<1>(property)); + void unpack(choice_t<2>, std::tuple property) { + unpack(std::move(property), std::index_sequence_for{}); + } + + template + void unpack(choice_t<1>, std::pair property) { + unpack(choice<0>, std::move(property.first), std::move(property.second)); } template - void unpack(char, Key &&key, Value &&... value) { + void unpack(choice_t<0>, Key &&key, Value &&... value) { static auto property{std::make_tuple(std::forward(key), std::forward(value)...)}; static internal::meta_prop_node node{ @@ -742,7 +752,7 @@ public: template auto prop(PropertyOrKey &&property_or_key, Value &&... value) { static_assert(sizeof...(Value) <= 1); - unpack(0, std::forward(property_or_key), std::forward(value)...); + unpack(choice<2>, std::forward(property_or_key), std::forward(value)...); return *this; } @@ -758,7 +768,7 @@ public: */ template auto props(Property... property) { - (unpack(0, property), ...); + (prop(property), ...); return *this; } diff --git a/test/entt/meta/meta.cpp b/test/entt/meta/meta.cpp index cd9a78516..cf586cb1b 100644 --- a/test/entt/meta/meta.cpp +++ b/test/entt/meta/meta.cpp @@ -156,14 +156,13 @@ struct Meta: ::testing::Test { .data("prop_bool"_hs) .prop(properties::prop_int, 0) .data("prop_int"_hs) - .prop(std::make_pair(properties::prop_bool, true)) - .prop(std::make_pair(properties::prop_int, 0)) + .prop(std::make_tuple(std::make_pair(properties::prop_bool, true), std::make_pair(properties::prop_int, 0))) .prop(properties::key_only) .data("key_only"_hs) .prop(properties::key_only) .data<&set, &get>("value"_hs) .data("prop_list"_hs) - .props(std::pair{properties::prop_bool, true}, std::pair{properties::prop_int, 0}, properties::key_only); + .props(std::make_pair(properties::prop_bool, true), std::make_pair(properties::prop_int, 0), properties::key_only); entt::meta().data<0u>("min"_hs).data<100u>("max"_hs);