diff --git a/docs/md/core.md b/docs/md/core.md
index 1baf9962f..0f7b48310 100644
--- a/docs/md/core.md
+++ b/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_.
+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_.
I will not describe them here in detail. Instead, I recommend reading the inline
documentation to those interested in the subject.
diff --git a/src/entt/core/memory.hpp b/src/entt/core/memory.hpp
index bf19333af..85ae8ee8b 100644
--- a/src/entt/core/memory.hpp
+++ b/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
+[[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept {
+ if constexpr(std::is_pointer_v>) {
+ return ptr;
+ } else {
+ return to_address(std::forward(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) {
using alloc_traits = std::allocator_traits;
- 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)...);
+ alloc_traits::construct(alloc, to_address(ptr), std::forward(args)...);
}
ENTT_CATCH {
alloc_traits::deallocate(alloc, ptr, 1u);
diff --git a/src/entt/entity/storage.hpp b/src/entt/entity/storage.hpp
index 2aec8262f..5f3647551 100644
--- a/src/entt/entity/storage.hpp
+++ b/src/entt/entity/storage.hpp
@@ -265,7 +265,7 @@ class basic_storage: public basic_sparse_set(it.index())));
+ auto *elem = to_address(assure_at_least(static_cast(it.index())));
entt::uninitialized_construct_using_allocator(elem, get_allocator(), std::forward(args)...);
}
ENTT_CATCH {
@@ -306,7 +306,7 @@ class basic_storage: public basic_sparse_set shared = std::make_shared();
+ auto *plain = &*shared;
+
+ ASSERT_EQ(entt::to_address(shared), plain);
+ ASSERT_EQ(entt::to_address(plain), plain);
+}
+
TEST(PoccaPocmaAndPocs, Functionalities) {
test::basic_test_allocator lhs;
test::basic_test_allocator rhs;