Browse Source

meta: deprecate meta_[any|handle]::operator*, use ::ref instead

Michele Caini 5 years ago
parent
commit
1d450ef27e
5 changed files with 25 additions and 26 deletions
  1. 8 16
      docs/md/meta.md
  2. 5 5
      src/entt/meta/factory.hpp
  3. 9 2
      src/entt/meta/meta.hpp
  4. 2 2
      test/entt/meta/meta_any.cpp
  5. 1 1
      test/entt/meta/meta_func.cpp

+ 8 - 16
docs/md/meta.md

@@ -227,7 +227,7 @@ different type than the one contained, so as to be able to handle the new
 instance.
 
 A particularly interesting feature of this class is that it can also be used as
-an opaque container for unmanaged objects:
+an opaque container for non-const unmanaged objects:
 
 ```cpp
 int value;
@@ -238,33 +238,25 @@ In other words, whenever `meta_any` intercepts a `reference_wrapper`, it acts as
 a reference to the original instance rather than making a copy of it. The
 contained object is never destroyed and users must ensure that its lifetime
 exceeds that of the container.<br/>
-Similarly, to create a copy that works as a _light_ reference for the managed
-object, it's possible to _dereference_ a given `meta_any` so as to invoke its
-aliasing constructor:
+Similarly, it's possible to create non-owning copies of `meta_any` from existing
+ones:
 
 ```cpp
 // aliasing constructor
 entt::meta_any ref = any.ref();
 ```
 
-This is also equivalent to:
-
-```cpp
-// indirection operator
-entt::meta_any ref = *any;
-```
-
-In both cases, it doesn't matter if the starting container actually holds an
-object or acts as a reference for unmanaged elements, the new instance thus
-created won't create copies and will only serve as a reference for the original
-item.<br/>
+In this case, it doesn't matter if the starting container actually holds an
+object or acts already as a reference for unmanaged elements, the new instance
+thus created won't create copies and will only serve as a reference for the
+original item.<br/>
 It means that, starting from the example above, both `ref` and` any` will point
 to the same object, whether it's initially contained in `any` or already an
 unmanaged one. This is particularly useful for passing instances of `meta_any`
 belonging to the external context by reference to a function or a constructor
 rather than making copies of them.
 
-The `meta_any` class has also a `type` member function that returns the meta
+The `meta_any` class also has a `type` member function that returns the meta
 type of the contained value, if any. The member functions `try_cast`, `cast` and
 `convert` are then used to know if the underlying object has a given type as a
 base or if it can be converted implicitly to it.

+ 5 - 5
src/entt/meta/factory.hpp

@@ -83,7 +83,7 @@ template<typename Type, auto Data>
         using helper_type = meta_function_helper_t<decltype(Data)>;
         using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
 
-        if(auto * const clazz = (*instance).try_cast<Type>(); clazz) {
+        if(auto * const clazz = instance.ref().try_cast<Type>(); clazz) {
             if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
                 std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
                 accepted = true;
@@ -93,7 +93,7 @@ template<typename Type, auto Data>
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
 
         if constexpr(!std::is_array_v<data_type>) {
-            if(auto * const clazz = (*instance).try_cast<Type>(); clazz) {
+            if(auto * const clazz = instance.ref().try_cast<Type>(); clazz) {
                 if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
                     std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
                     accepted = true;
@@ -129,13 +129,13 @@ template<typename Type, auto Data, typename Policy>
     };
 
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
-        auto * const clazz = (*instance).try_cast<Type>();
+        auto * const clazz = instance.ref().try_cast<Type>();
         return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         if constexpr(std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
             return meta_any{};
         } else {
-            auto * const clazz = (*instance).try_cast<Type>();
+            auto * const clazz = instance.ref().try_cast<Type>();
             return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
         }
     } else if constexpr(std::is_pointer_v<std::decay_t<decltype(Data)>>) {
@@ -179,7 +179,7 @@ template<typename Type, auto Candidate, typename Policy, std::size_t... Indexes>
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Candidate)>>>) {
         return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
     } else {
-        auto * const clazz = (*instance).try_cast<Type>();
+        auto * const clazz = instance.ref().try_cast<Type>();
         return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
     }
 }

+ 9 - 2
src/entt/meta/meta.hpp

@@ -455,6 +455,7 @@ public:
      * @brief Indirection operator for aliasing construction.
      * @return A meta any that shares a reference to an unmanaged object.
      */
+    [[deprecated("use ::ref instead")]]
     [[nodiscard]] meta_any operator*() const ENTT_NOEXCEPT {
         return ref();
     }
@@ -575,7 +576,7 @@ struct meta_container::meta_iterator {
      * @return The actual iterator, properly wrapped.
      */
     [[nodiscard]] meta_any handle() const ENTT_NOEXCEPT {
-        return *it;
+        return it.ref();
     }
 
     /**
@@ -703,7 +704,7 @@ struct meta_handle {
         : meta_handle{}
     {
         if constexpr(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>) {
-            any = *value;
+            any = value.ref();
         } else {
             static_assert(std::is_lvalue_reference_v<Type>, "Lvalue reference required");
             any = std::ref(value);
@@ -711,6 +712,12 @@ struct meta_handle {
     }
 
     /*! @copydoc meta_any::operator* */
+    [[nodiscard]] meta_any ref() const {
+        return any;
+    }
+
+    /*! @copydoc meta_any::operator* */
+    [[deprecated("use ::ref instead")]]
     [[nodiscard]] meta_any operator*() const {
         return any;
     }

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

@@ -99,7 +99,7 @@ TEST_F(MetaAny, SBOInPlaceTypeConstruction) {
     ASSERT_NE(entt::meta_any{3}, any);
 }
 
-TEST_F(MetaAny, SBOAsAliasConstruction) {
+TEST_F(MetaAny, SBOAsRefConstruction) {
     int value = 3;
     int other = 42;
     entt::meta_any any{std::ref(value)};
@@ -190,7 +190,7 @@ TEST_F(MetaAny, NoSBOInPlaceTypeConstruction) {
     ASSERT_NE(entt::meta_any{fat_t{}}, any);
 }
 
-TEST_F(MetaAny, NoSBOAsAliasConstruction) {
+TEST_F(MetaAny, NoSBOAsRefConstruction) {
     int value = 3;
     fat_t instance{&value};
     entt::meta_any any{std::ref(instance)};

+ 1 - 1
test/entt/meta/meta_func.cpp

@@ -295,7 +295,7 @@ TEST_F(MetaFunc, AsVoid) {
     ASSERT_EQ(instance.value, 42);
 }
 
-TEST_F(MetaFunc, AsAlias) {
+TEST_F(MetaFunc, AsRef) {
     func_t instance{};
     auto func = entt::resolve<func_t>().func("a"_hs);
     func.invoke(instance).cast<int>() = 3;