소스 검색

meta: support tuple as properties

Michele Caini 6 년 전
부모
커밋
520ccfcd06
3개의 변경된 파일37개의 추가작업 그리고 18개의 파일을 삭제
  1. 13 3
      docs/md/meta.md
  2. 22 12
      src/entt/meta/factory.hpp
  3. 2 3
      test/entt/meta/meta.cpp

+ 13 - 3
docs/md/meta.md

@@ -509,9 +509,19 @@ Furthermore, the `prop` function supports different formats for properties:
   entt::meta<my_type>().type("reflected_type"_hs).prop(my_enum::key_only);
   entt::meta<my_type>().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<my_type>().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
 ```cpp
 entt::meta<my_type>()
 entt::meta<my_type>()

+ 22 - 12
src/entt/meta/factory.hpp

@@ -35,7 +35,7 @@ struct meta_function_helper<Ret(Args...)> {
     using return_type = std::remove_cv_t<std::remove_reference_t<Ret>>;
     using return_type = std::remove_cv_t<std::remove_reference_t<Ret>>;
     using args_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
     using args_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
 
 
-    static constexpr auto size = sizeof...(Args);
+    static constexpr std::index_sequence_for<Args...> index_sequence{};
     static constexpr auto is_const = false;
     static constexpr auto is_const = false;
 
 
     static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
     static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
@@ -415,10 +415,10 @@ public:
             type,
             type,
             nullptr,
             nullptr,
             nullptr,
             nullptr,
-            helper_type::size,
+            helper_type::index_sequence.size(),
             &helper_type::arg,
             &helper_type::arg,
             [](meta_any * const any) {
             [](meta_any * const any) {
-                return internal::invoke<Type, Func, Policy>({}, any, std::make_index_sequence<helper_type::size>{});
+                return internal::invoke<Type, Func, Policy>({}, any, helper_type::index_sequence);
             }
             }
         };
         };
 
 
@@ -448,10 +448,10 @@ public:
             type,
             type,
             nullptr,
             nullptr,
             nullptr,
             nullptr,
-            helper_type::size,
+            helper_type::index_sequence.size(),
             &helper_type::arg,
             &helper_type::arg,
             [](meta_any * const any) {
             [](meta_any * const any) {
-                return internal::construct<Type, std::remove_cv_t<std::remove_reference_t<Args>>...>(any, std::make_index_sequence<helper_type::size>{});
+                return internal::construct<Type, std::remove_cv_t<std::remove_reference_t<Args>>...>(any, helper_type::index_sequence);
             }
             }
         };
         };
 
 
@@ -650,13 +650,13 @@ public:
             type,
             type,
             nullptr,
             nullptr,
             nullptr,
             nullptr,
-            helper_type::size,
+            helper_type::index_sequence.size(),
             helper_type::is_const,
             helper_type::is_const,
             !std::is_member_function_pointer_v<decltype(Candidate)>,
             !std::is_member_function_pointer_v<decltype(Candidate)>,
             &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
             &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
             &helper_type::arg,
             &helper_type::arg,
             [](meta_handle handle, meta_any *any) {
             [](meta_handle handle, meta_any *any) {
-                return internal::invoke<Type, Candidate, Policy>(handle, any, std::make_index_sequence<helper_type::size>{});
+                return internal::invoke<Type, Candidate, Policy>(handle, any, helper_type::index_sequence);
             }
             }
         };
         };
 
 
@@ -696,13 +696,23 @@ class extended_meta_factory: public meta_factory<Type> {
         return node && (node->key() == key || duplicate(key, node->next));
         return node && (node->key() == key || duplicate(key, node->next));
     }
     }
 
 
+    template<typename... Property, std::size_t... Index>
+    void unpack(std::tuple<Property...> property, std::index_sequence<Index...>) {
+        (unpack(choice<2>, std::get<Index>(property)), ...);
+    }
+
     template<typename... Property>
     template<typename... Property>
-    void unpack(int, std::pair<Property...> property) {
-        unpack(0, std::get<0>(property), std::get<1>(property));
+    void unpack(choice_t<2>, std::tuple<Property...> property) {
+        unpack(std::move(property), std::index_sequence_for<Property...>{});
+    }
+
+    template<typename... KeyOrValue>
+    void unpack(choice_t<1>, std::pair<KeyOrValue...> property) {
+        unpack(choice<0>, std::move(property.first), std::move(property.second));
     }
     }
 
 
     template<typename Key, typename... Value>
     template<typename Key, typename... Value>
-    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>(key), std::forward<Value>(value)...)};
         static auto property{std::make_tuple(std::forward<Key>(key), std::forward<Value>(value)...)};
 
 
         static internal::meta_prop_node node{
         static internal::meta_prop_node node{
@@ -742,7 +752,7 @@ public:
     template<typename PropertyOrKey, typename... Value>
     template<typename PropertyOrKey, typename... Value>
     auto prop(PropertyOrKey &&property_or_key, Value &&... value) {
     auto prop(PropertyOrKey &&property_or_key, Value &&... value) {
         static_assert(sizeof...(Value) <= 1);
         static_assert(sizeof...(Value) <= 1);
-        unpack(0, std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
+        unpack(choice<2>, std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
         return *this;
         return *this;
     }
     }
 
 
@@ -758,7 +768,7 @@ public:
      */
      */
     template <typename... Property>
     template <typename... Property>
     auto props(Property... property) {
     auto props(Property... property) {
-        (unpack(0, property), ...);
+        (prop(property), ...);
         return *this;
         return *this;
     }
     }
 
 

+ 2 - 3
test/entt/meta/meta.cpp

@@ -156,14 +156,13 @@ struct Meta: ::testing::Test {
                 .data<properties::prop_bool>("prop_bool"_hs)
                 .data<properties::prop_bool>("prop_bool"_hs)
                     .prop(properties::prop_int, 0)
                     .prop(properties::prop_int, 0)
                 .data<properties::prop_int>("prop_int"_hs)
                 .data<properties::prop_int>("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)
                     .prop(properties::key_only)
                 .data<properties::key_only>("key_only"_hs)
                 .data<properties::key_only>("key_only"_hs)
                     .prop(properties::key_only)
                     .prop(properties::key_only)
                 .data<&set<properties>, &get<properties>>("value"_hs)
                 .data<&set<properties>, &get<properties>>("value"_hs)
                 .data<properties::prop_list>("prop_list"_hs)
                 .data<properties::prop_list>("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<unsigned int>().data<0u>("min"_hs).data<100u>("max"_hs);
         entt::meta<unsigned int>().data<0u>("min"_hs).data<100u>("max"_hs);