Explorar el Código

any/meta/poly: as_ref const and non-const overloads

Michele Caini hace 5 años
padre
commit
6123e4ac8a
Se han modificado 4 ficheros con 40 adiciones y 17 borrados
  1. 1 2
      TODO
  2. 17 8
      src/entt/core/any.hpp
  3. 13 6
      src/entt/meta/meta.hpp
  4. 9 1
      src/entt/poly/poly.hpp

+ 1 - 2
TODO

@@ -18,9 +18,8 @@
   - ...
   - ...
 
 
 WIP:
 WIP:
-* HP: any/meta_any/poly: ::REF -> ::CREF?
+* HP: const poly storage function for the registry
 * HP: meta, support for custom deref function other than operator*
 * HP: meta, support for custom deref function other than operator*
-* HP: meta, as_cref_t other than as_ref_t
 * HP: headless (sparse set only) view
 * HP: headless (sparse set only) view
 * HP: pass the registry to pools, basic poly storage should have only component member
 * HP: pass the registry to pools, basic poly storage should have only component member
 * HP: make view pack work also with groups, make packs input iterator only, add view adapter for external sources
 * HP: make view pack work also with groups, make packs input iterator only, add view adapter for external sources

+ 17 - 8
src/entt/core/any.hpp

@@ -16,7 +16,7 @@ namespace entt {
 
 
 /*! @brief A SBO friendly, type-safe container for single values of any type. */
 /*! @brief A SBO friendly, type-safe container for single values of any type. */
 class any {
 class any {
-    enum class operation { COPY, MOVE, DTOR, ADDR, CADDR, REF, TYPE };
+    enum class operation { COPY, MOVE, DTOR, ADDR, CADDR, REF, CREF, TYPE };
 
 
     using storage_type = std::aligned_storage_t<sizeof(double[2]), alignof(double[2])>;
     using storage_type = std::aligned_storage_t<sizeof(double[2]), alignof(double[2])>;
     using vtable_type = const void *(const operation, const any &, const void *);
     using vtable_type = const void *(const operation, const any &, const void *);
@@ -39,7 +39,8 @@ class any {
         } else if constexpr(std::is_lvalue_reference_v<Type>) {
         } else if constexpr(std::is_lvalue_reference_v<Type>) {
             switch(op) {
             switch(op) {
             case operation::REF:
             case operation::REF:
-                as_any(to).vtable = from.vtable;
+            case operation::CREF:
+                as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
                 [[fallthrough]];
                 [[fallthrough]];
             case operation::COPY:
             case operation::COPY:
             case operation::MOVE:
             case operation::MOVE:
@@ -72,7 +73,8 @@ class any {
             case operation::CADDR:
             case operation::CADDR:
                 return instance;
                 return instance;
             case operation::REF:
             case operation::REF:
-                as_any(to).vtable = basic_vtable<Type &>;
+            case operation::CREF:
+                as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
                 as_any(to).instance = instance;
                 as_any(to).instance = instance;
                 break;
                 break;
             case operation::TYPE:
             case operation::TYPE:
@@ -84,6 +86,10 @@ class any {
             case operation::COPY:
             case operation::COPY:
                 as_any(to).instance = new Type{*static_cast<const Type *>(from.instance)};
                 as_any(to).instance = new Type{*static_cast<const Type *>(from.instance)};
                 break;
                 break;
+            case operation::REF:
+            case operation::CREF:
+                as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
+                [[fallthrough]];
             case operation::MOVE:
             case operation::MOVE:
                 as_any(to).instance = from.instance;
                 as_any(to).instance = from.instance;
                 break;
                 break;
@@ -93,10 +99,6 @@ class any {
             case operation::ADDR:
             case operation::ADDR:
             case operation::CADDR:
             case operation::CADDR:
                 return from.instance;
                 return from.instance;
-            case operation::REF:
-                as_any(to).vtable = basic_vtable<Type &>;
-                as_any(to).instance = from.instance;
-                break;
             case operation::TYPE:
             case operation::TYPE:
                 as_type_info(to) = type_id<Type>();
                 as_type_info(to) = type_id<Type>();
                 break;
                 break;
@@ -251,12 +253,19 @@ public:
      * @param other A reference to an object that isn't necessarily initialized.
      * @param other A reference to an object that isn't necessarily initialized.
      * @return An any that shares a reference to an unmanaged object.
      * @return An any that shares a reference to an unmanaged object.
      */
      */
-    [[nodiscard]] friend any as_ref(const any &other) ENTT_NOEXCEPT {
+    [[nodiscard]] friend any as_ref(any &other) ENTT_NOEXCEPT {
         any ref{};
         any ref{};
         other.vtable(operation::REF, other, &ref);
         other.vtable(operation::REF, other, &ref);
         return ref;
         return ref;
     }
     }
 
 
+    /*! @copydoc as_ref */
+    [[nodiscard]] friend any as_ref(const any &other) ENTT_NOEXCEPT {
+        any ref{};
+        other.vtable(operation::CREF, other, &ref);
+        return ref;
+    }
+
 private:
 private:
     vtable_type *vtable;
     vtable_type *vtable;
     union { const void *instance; storage_type storage; };
     union { const void *instance; storage_type storage; };

+ 13 - 6
src/entt/meta/meta.hpp

@@ -221,7 +221,7 @@ public:
     template<typename Type>
     template<typename Type>
     meta_any(std::reference_wrapper<Type> value)
     meta_any(std::reference_wrapper<Type> value)
         : storage{value},
         : storage{value},
-          vtable{&basic_vtable<Type>},
+          vtable{&basic_vtable<std::remove_const_t<Type>>},
           node{internal::meta_info<Type>::resolve()}
           node{internal::meta_info<Type>::resolve()}
     {}
     {}
 
 
@@ -500,6 +500,13 @@ public:
      * @param other A reference to an object that isn't necessarily initialized.
      * @param other A reference to an object that isn't necessarily initialized.
      * @return A meta any that shares a reference to an unmanaged object.
      * @return A meta any that shares a reference to an unmanaged object.
      */
      */
+    [[nodiscard]] friend meta_any as_ref(meta_any &other) ENTT_NOEXCEPT {
+        meta_any ref = as_ref(std::as_const(other));
+        ref.storage = as_ref(other.storage);
+        return ref;
+    }
+
+    /*! @copydoc as_ref */
     [[nodiscard]] friend meta_any as_ref(const meta_any &other) ENTT_NOEXCEPT {
     [[nodiscard]] friend meta_any as_ref(const meta_any &other) ENTT_NOEXCEPT {
         meta_any ref{};
         meta_any ref{};
         ref.node = other.node;
         ref.node = other.node;
@@ -1655,9 +1662,9 @@ class meta_sequence_container::meta_iterator {
     template<typename It>
     template<typename It>
     [[nodiscard]] static meta_any deref(meta_any any) {
     [[nodiscard]] static meta_any deref(meta_any any) {
         if constexpr(std::is_const_v<std::remove_reference_t<decltype(*std::declval<It>())>>) {
         if constexpr(std::is_const_v<std::remove_reference_t<decltype(*std::declval<It>())>>) {
-            return *any.cast<It &>();
+            return *any.cast<const It &>();
         } else {
         } else {
-            return std::ref(*any.cast<It &>());
+            return std::ref(*any.cast<const It &>());
         }
         }
     }
     }
 
 
@@ -1901,9 +1908,9 @@ class meta_associative_container::meta_iterator {
     template<bool KeyOnly, typename It>
     template<bool KeyOnly, typename It>
     [[nodiscard]] static meta_any key(meta_any any) {
     [[nodiscard]] static meta_any key(meta_any any) {
         if constexpr(KeyOnly) {
         if constexpr(KeyOnly) {
-            return *any.cast<It &>();
+            return *any.cast<const It &>();
         } else {
         } else {
-            return any.cast<It &>()->first;
+            return any.cast<const It &>()->first;
         }
         }
     }
     }
 
 
@@ -1912,7 +1919,7 @@ class meta_associative_container::meta_iterator {
         if constexpr(KeyOnly) {
         if constexpr(KeyOnly) {
             return meta_any{};
             return meta_any{};
         } else {
         } else {
-            return std::ref(any.cast<It &>()->second);
+            return std::ref(any.cast<const It &>()->second);
         }
         }
     }
     }
 
 

+ 9 - 1
src/entt/poly/poly.hpp

@@ -105,6 +105,7 @@ public:
      */
      */
     template<typename Type>
     template<typename Type>
     [[nodiscard]] static const auto * instance() {
     [[nodiscard]] static const auto * instance() {
+        static_assert(std::is_same_v<Type, std::decay_t<Type>>);
         static const auto vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
         static const auto vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
         return &vtable;
         return &vtable;
     }
     }
@@ -205,7 +206,7 @@ public:
     template<typename Type>
     template<typename Type>
     poly(std::reference_wrapper<Type> value)
     poly(std::reference_wrapper<Type> value)
         : storage{value},
         : storage{value},
-          vtable{poly_vtable<Concept>::template instance<Type>()}
+          vtable{poly_vtable<Concept>::template instance<std::remove_const_t<Type>>()}
     {}
     {}
 
 
     /**
     /**
@@ -314,6 +315,13 @@ public:
      * @param other A reference to an object that isn't necessarily initialized.
      * @param other A reference to an object that isn't necessarily initialized.
      * @return A poly that shares a reference to an unmanaged object.
      * @return A poly that shares a reference to an unmanaged object.
      */
      */
+    [[nodiscard]] friend poly as_ref(poly &other) ENTT_NOEXCEPT {
+        poly ref = as_ref(std::as_const(other));
+        ref.storage = as_ref(other.storage);
+        return ref;
+    }
+
+    /*! @copydoc as_ref */
     [[nodiscard]] friend poly as_ref(const poly &other) ENTT_NOEXCEPT {
     [[nodiscard]] friend poly as_ref(const poly &other) ENTT_NOEXCEPT {
         poly ref;
         poly ref;
         ref.storage = as_ref(other.storage);
         ref.storage = as_ref(other.storage);