summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std/memory_resource
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-08-03 14:00:47 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-08-03 15:30:36 +0100
commit13a1ac9f6f700f4e214fcc83b122a4a405c6b13d (patch)
treea09d223b37dea4182bfd8a16f7ec75a639c4553c /libstdc++-v3/include/std/memory_resource
parent9bd87e388724baab9597ef232ea7e855c99eb7d7 (diff)
downloadgcc-13a1ac9f6f700f4e214fcc83b122a4a405c6b13d.tar.gz
libstdc++: Specialize allocator_traits<pmr::polymorphic_allocator<T>>
This adds a partial specialization of allocator_traits, similar to what was already done for std::allocator. This means that most uses of polymorphic_allocator via the traits can avoid the metaprogramming overhead needed to deduce the properties from polymorphic_allocator. In addition, I'm changing polymorphic_allocator::delete_object to invoke the destructor (or pseudo-destructor) directly, rather than calling allocator_traits::destroy, which calls polymorphic_allocator::destroy (which is deprecated). This is observable if a user has specialized allocator_traits<polymorphic_allocator<Foo>> and expects to see its destroy member function called. I consider explicit specializations of allocator_traits to be wrong-headed, and this use case seems unnecessary to support. So delete_object just invokes the destructor directly. Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/std/memory_resource (polymorphic_allocator::delete_object): Call destructor directly instead of using destroy. (allocator_traits<polymorphic_allocator<T>>): Define partial specialization.
Diffstat (limited to 'libstdc++-v3/include/std/memory_resource')
-rw-r--r--libstdc++-v3/include/std/memory_resource132
1 files changed, 131 insertions, 1 deletions
diff --git a/libstdc++-v3/include/std/memory_resource b/libstdc++-v3/include/std/memory_resource
index cdc5e5d98b1..6bca0afa018 100644
--- a/libstdc++-v3/include/std/memory_resource
+++ b/libstdc++-v3/include/std/memory_resource
@@ -232,7 +232,7 @@ namespace pmr
void
delete_object(_Up* __p)
{
- destroy(__p);
+ __p->~_Up();
deallocate_object(__p);
}
#endif // C++2a
@@ -381,6 +381,136 @@ namespace pmr
{ return !(__a == __b); }
#endif
+} // namespace pmr
+
+ /// Partial specialization for std::pmr::polymorphic_allocator
+ template<typename _Tp>
+ struct allocator_traits<pmr::polymorphic_allocator<_Tp>>
+ {
+ /// The allocator type
+ using allocator_type = pmr::polymorphic_allocator<_Tp>;
+
+ /// The allocated type
+ using value_type = _Tp;
+
+ /// The allocator's pointer type.
+ using pointer = _Tp*;
+
+ /// The allocator's const pointer type.
+ using const_pointer = const _Tp*;
+
+ /// The allocator's void pointer type.
+ using void_pointer = void*;
+
+ /// The allocator's const void pointer type.
+ using const_void_pointer = const void*;
+
+ /// The allocator's difference type
+ using difference_type = std::ptrdiff_t;
+
+ /// The allocator's size type
+ using size_type = std::size_t;
+
+ /** @{
+ * A `polymorphic_allocator` does not propagate when a
+ * container is copied, moved, or swapped.
+ */
+ using propagate_on_container_copy_assignment = false_type;
+ using propagate_on_container_move_assignment = false_type;
+ using propagate_on_container_swap = false_type;
+
+ static allocator_type
+ select_on_container_copy_construction(const allocator_type&) noexcept
+ { return allocator_type(); }
+ /// @}
+
+ /// Whether all instances of the allocator type compare equal.
+ using is_always_equal = false_type;
+
+ template<typename _Up>
+ using rebind_alloc = pmr::polymorphic_allocator<_Up>;
+
+ template<typename _Up>
+ using rebind_traits = allocator_traits<pmr::polymorphic_allocator<_Up>>;
+
+ /**
+ * @brief Allocate memory.
+ * @param __a An allocator.
+ * @param __n The number of objects to allocate space for.
+ *
+ * Calls `a.allocate(n)`.
+ */
+ [[nodiscard]] static pointer
+ allocate(allocator_type& __a, size_type __n)
+ { return __a.allocate(__n); }
+
+ /**
+ * @brief Allocate memory.
+ * @param __a An allocator.
+ * @param __n The number of objects to allocate space for.
+ * @return Memory of suitable size and alignment for `n` objects
+ * of type `value_type`.
+ *
+ * The third parameter is ignored..
+ *
+ * Returns `a.allocate(n)`.
+ */
+ [[nodiscard]] static pointer
+ allocate(allocator_type& __a, size_type __n, const_void_pointer)
+ { return __a.allocate(__n); }
+
+ /**
+ * @brief Deallocate memory.
+ * @param __a An allocator.
+ * @param __p Pointer to the memory to deallocate.
+ * @param __n The number of objects space was allocated for.
+ *
+ * Calls `a.deallocate(p, n)`.
+ */
+ static void
+ deallocate(allocator_type& __a, pointer __p, size_type __n)
+ { __a.deallocate(__p, __n); }
+
+ /**
+ * @brief Construct an object of type `_Up`
+ * @param __a An allocator.
+ * @param __p Pointer to memory of suitable size and alignment for
+ * an object of type `_Up`.
+ * @param __args Constructor arguments.
+ *
+ * Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
+ * in C++11, C++14 and C++17. Changed in C++20 to call
+ * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
+ */
+ template<typename _Up, typename... _Args>
+ static void
+ construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+ { __a.construct(__p, std::forward<_Args>(__args)...); }
+
+ /**
+ * @brief Destroy an object of type `_Up`
+ * @param __a An allocator.
+ * @param __p Pointer to the object to destroy
+ *
+ * Calls `p->_Up()`.
+ */
+ template<typename _Up>
+ static _GLIBCXX20_CONSTEXPR void
+ destroy(allocator_type&, _Up* __p)
+ noexcept(is_nothrow_destructible<_Up>::value)
+ { __p->~_Up(); }
+
+ /**
+ * @brief The maximum supported allocation size
+ * @return `numeric_limits<size_t>::max() / sizeof(value_type)`
+ */
+ static _GLIBCXX20_CONSTEXPR size_type
+ max_size(const allocator_type&) noexcept
+ { return size_t(-1) / sizeof(value_type); }
+ };
+
+namespace pmr
+{
/// Parameters for tuning a pool resource's behaviour.
struct pool_options
{