Browse Source

meta: more on properties (close #341)

Michele Caini 6 years ago
parent
commit
93fd1757f8
3 changed files with 68 additions and 29 deletions
  1. 35 6
      docs/md/meta.md
  2. 31 21
      src/entt/meta/factory.hpp
  3. 2 2
      test/entt/meta/meta.cpp

+ 35 - 6
docs/md/meta.md

@@ -483,26 +483,55 @@ itself. The latter can be used to attach properties to the last created meta
 object.<br/>
 Apparently, it's more difficult to say than to do:
 
+```cpp
+entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
 ```
+
+Properties are always in the key/value form. There are no restrictions on the
+type of the key or value, as long as they are copy constructible objects.<br/>
+Furthermore, the `prop` function supports different formats for properties:
+
+* Properties as key/value pairs:
+
+  ```cpp
+  entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
+  ```
+
+* Properties as _`std::get<1>`-table_ objects:
+
+  ```cpp
+  entt::meta<my_type>().type("reflected_type"_hs).prop(std::make_pair("tooltip"_hs, "message"));
+  ```
+
+* Key only properties:
+
+  ```cpp
+  entt::meta<my_type>().type("reflected_type"_hs).prop("tooltip"_hs, "message");
+  ```
+
+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:
+
+```cpp
 entt::meta<my_type>()
         .type("reflected_type"_hs)
             .prop(entt::hashed_string{"Name"}, "Reflected Type")
-            .prop("tooltip"_hs, "message")
+        .data<&my_type::data_member>("member"_hs)
+            .prop(std::make_pair("tooltip"_hs, "Member"))
             .prop(my_enum::a_value, 42);
 ```
 
-Properties are always in the key/value form. There are no restrictions on the
-type of the key or value, as long as they are copy constructible objects.<br/>
 The meta objects for which properties are supported are currently the meta
 types, meta constructors, meta data and meta functions. It's not possible to
 attach properties to other types of meta objects and the factory returned as a
 result of their construction won't allow such an operation.
 
-The meta objects that support properties offer then a couple of member functions
-named `prop` to iterate them at once and to search a specific property by key:
+These types offer a couple of member functions named `prop` to iterate all
+properties at once or to search a specific property by key:
 
 ```cpp
-// iterate all the properties of a meta type
+// iterate all properties of a meta type
 entt::resolve<my_type>().prop([](auto prop) {
     // ...
 });

+ 31 - 21
src/entt/meta/factory.hpp

@@ -696,29 +696,18 @@ class extended_meta_factory: public meta_factory<Type> {
         return node && (node->key() == key || duplicate(key, node->next));
     }
 
-    extended_meta_factory(entt::internal::meta_prop_node **target)
-        : props{target}
-    {}
+    template<typename Property>
+    auto unpack(int, Property &&property)
+    -> decltype(std::get<1>(property), void()) {
+        unpack(0, std::get<0>(property), std::get<1>(property));
+    }
 
-public:
-    /**
-     * @brief Assigns properties to the last meta object created.
-     *
-     * Both the key and the value (if any) must be at least copy constructible.
-     *
-     * @tparam Key Type of the property key.
-     * @tparam Value Optional type of the property value.
-     * @param pkey Property key.
-     * @param pvalue Optional property value.
-     * @return A meta factory for the parent type.
-     */
     template<typename Key, typename... Value>
-    auto prop(Key &&pkey, Value &&... pvalue) {
-        static_assert(sizeof...(Value) <= 1);
+    void unpack(char, Key &&pkey, Value &&... pvalue) {
         static auto property{std::make_tuple(std::forward<Key>(pkey), std::forward<Value>(pvalue)...)};
 
         static internal::meta_prop_node node{
-            *props,
+            *curr,
             []() -> meta_any {
                 return std::get<0>(property);
             },
@@ -731,14 +720,35 @@ public:
             }
         };
 
-        ENTT_ASSERT(!duplicate(node.key(), *props));
-        *props = &node;
+        ENTT_ASSERT(!duplicate(node.key(), *curr));
+        *curr = &node;
+    }
 
+    extended_meta_factory(entt::internal::meta_prop_node **target)
+        : curr{target}
+    {}
+
+public:
+    /**
+     * @brief Assigns properties to the last meta object created.
+     *
+     * Both the key and the value (if any) must be at least copy constructible.
+     *
+     * @tparam PropertyOrKey Type of the property or property key.
+     * @tparam Value Optional type of the property value.
+     * @param property_or_key Property or property key.
+     * @param value Optional property value.
+     * @return A meta factory for the parent type.
+     */
+    template<typename PropertyOrKey, typename... Value>
+    auto prop(PropertyOrKey &&property_or_key, Value &&... value) {
+        static_assert(sizeof...(Value) <= 1);
+        unpack(0, std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
         return *this;
     }
 
 private:
-    entt::internal::meta_prop_node **props{nullptr};
+    entt::internal::meta_prop_node **curr{nullptr};
 };
 
 

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

@@ -155,8 +155,8 @@ struct Meta: ::testing::Test {
                 .data<properties::prop_bool>("prop_bool"_hs)
                     .prop(properties::prop_int, 0)
                 .data<properties::prop_int>("prop_int"_hs)
-                    .prop(properties::prop_bool, true)
-                    .prop(properties::prop_int, 0)
+                    .prop(std::make_pair(properties::prop_bool, true))
+                    .prop(std::make_pair(properties::prop_int, 0))
                     .prop(properties::key_only)
                 .data<properties::key_only>("key_only"_hs)
                     .prop(properties::key_only)