فهرست منبع

core: reintroduce to_address (it's not available everywhere yet, I need to find a solution to inject it when needed)

skypjack 2 ماه پیش
والد
کامیت
c2d68e242a
4فایلهای تغییر یافته به همراه30 افزوده شده و 7 حذف شده
  1. 3 3
      docs/md/core.md
  2. 17 2
      src/entt/core/memory.hpp
  3. 2 2
      src/entt/entity/storage.hpp
  4. 8 0
      test/entt/core/memory.cpp

+ 3 - 3
docs/md/core.md

@@ -445,9 +445,9 @@ Some are geared towards simplifying the implementation of (internal or external)
 allocator aware containers. Others are designed to help the developer with
 everyday problems.
 
-The former are very specific and for niche problems. For example, there are
-tools designed to help forget the meaning of acronyms like _POCCA_, _POCMA_ or
-_POCS_.<br/>
+The former are very specific and for niche problems. These are tools designed to
+unwrap fancy or plain pointers (`to_address`) or to help forget the meaning of
+acronyms like _POCCA_, _POCMA_ or _POCS_.<br/>
 I will not describe them here in detail. Instead, I recommend reading the inline
 documentation to those interested in the subject.
 

+ 17 - 2
src/entt/core/memory.hpp

@@ -10,6 +10,21 @@
 
 namespace entt {
 
+/**
+ * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
+ * @tparam Type Pointer type.
+ * @param ptr Fancy or raw pointer.
+ * @return A raw pointer that represents the address of the original pointer.
+ */
+template<typename Type>
+[[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
+    if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
+        return ptr;
+    } else {
+        return to_address(std::forward<Type>(ptr).operator->());
+    }
+}
+
 /**
  * @brief Utility function to design allocation-aware containers.
  * @tparam Allocator Type of allocator.
@@ -76,7 +91,7 @@ struct allocation_deleter: private Allocator {
      */
     constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
         using alloc_traits = std::allocator_traits<Allocator>;
-        alloc_traits::destroy(*this, std::to_address(ptr));
+        alloc_traits::destroy(*this, to_address(ptr));
         alloc_traits::deallocate(*this, ptr, 1u);
     }
 };
@@ -101,7 +116,7 @@ constexpr auto allocate_unique(Allocator &allocator, Args &&...args) {
     auto ptr = alloc_traits::allocate(alloc, 1u);
 
     ENTT_TRY {
-        alloc_traits::construct(alloc, std::to_address(ptr), std::forward<Args>(args)...);
+        alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...);
     }
     ENTT_CATCH {
         alloc_traits::deallocate(alloc, ptr, 1u);

+ 2 - 2
src/entt/entity/storage.hpp

@@ -265,7 +265,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
         const auto it = base_type::try_emplace(entt, force_back);
 
         ENTT_TRY {
-            auto *elem = std::to_address(assure_at_least(static_cast<size_type>(it.index())));
+            auto *elem = to_address(assure_at_least(static_cast<size_type>(it.index())));
             entt::uninitialized_construct_using_allocator(elem, get_allocator(), std::forward<Args>(args)...);
         }
         ENTT_CATCH {
@@ -306,7 +306,7 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
     void move_to(const std::size_t lhs, const std::size_t rhs) {
         auto &elem = element_at(lhs);
         allocator_type allocator{get_allocator()};
-        entt::uninitialized_construct_using_allocator(std::to_address(assure_at_least(rhs)), allocator, std::move(elem));
+        entt::uninitialized_construct_using_allocator(to_address(assure_at_least(rhs)), allocator, std::move(elem));
         alloc_traits::destroy(allocator, std::addressof(elem));
     }
 

+ 8 - 0
test/entt/core/memory.cpp

@@ -13,6 +13,14 @@
 #include "../../common/throwing_type.hpp"
 #include "../../common/tracked_memory_resource.hpp"
 
+TEST(ToAddress, Functionalities) {
+    const std::shared_ptr<int> shared = std::make_shared<int>();
+    auto *plain = &*shared;
+
+    ASSERT_EQ(entt::to_address(shared), plain);
+    ASSERT_EQ(entt::to_address(plain), plain);
+}
+
 TEST(PoccaPocmaAndPocs, Functionalities) {
     test::basic_test_allocator<int> lhs;
     test::basic_test_allocator<int> rhs;