mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 00:56:41 +00:00
[libc++][memory] P2652R2: Disallow Specialization of allocator_traits
(#79978)
Implements P2652R2 <https://wg21.link/P2652R2>: - https://eel.is/c++draft/allocator.requirements.general - https://eel.is/c++draft/memory.syn - https://eel.is/c++draft/allocator.traits.general - https://eel.is/c++draft/allocator.traits.members - https://eel.is/c++draft/diff.cpp20.concepts - https://eel.is/c++draft/diff.cpp20.utilities --------- Co-authored-by: Zingam <zingam@outlook.com>
This commit is contained in:
parent
da437330be
commit
7d78ccf7d5
@ -304,7 +304,7 @@ Status
|
||||
---------------------------------------------------------------------
|
||||
``__cpp_lib_adaptor_iterator_pair_constructor`` ``202106L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_allocate_at_least`` ``202106L``
|
||||
``__cpp_lib_allocate_at_least`` ``202302L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_associative_heterogeneous_erasure`` *unimplemented*
|
||||
--------------------------------------------------- -----------------
|
||||
|
@ -37,7 +37,9 @@ What's New in Libc++ 19.0.0?
|
||||
|
||||
Implemented Papers
|
||||
------------------
|
||||
|
||||
- P2637R3 - Member ``visit``
|
||||
- P2652R2 - Disallow User Specialization of ``allocator_traits``
|
||||
|
||||
|
||||
Improvements and New Features
|
||||
|
@ -115,7 +115,7 @@
|
||||
"`P2679R2 <https://wg21.link/P2679R2>`__","LWG", "Fixing ``std::start_lifetime_as`` for arrays","February 2023","","",""
|
||||
"`P2674R1 <https://wg21.link/P2674R1>`__","LWG", "A trait for implicit lifetime types","February 2023","","",""
|
||||
"`P2655R3 <https://wg21.link/P2655R3>`__","LWG", "``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","February 2023","","",""
|
||||
"`P2652R2 <https://wg21.link/P2652R2>`__","LWG", "Disallow User Specialization of ``allocator_traits``","February 2023","","",""
|
||||
"`P2652R2 <https://wg21.link/P2652R2>`__","LWG", "Disallow User Specialization of ``allocator_traits``","February 2023","|Complete|","19.0",""
|
||||
"`P2787R1 <https://wg21.link/P2787R1>`__","LWG", "``pmr::generator`` - Promise Types are not Values","February 2023","","",""
|
||||
"`P2614R2 <https://wg21.link/P2614R2>`__","LWG", "Deprecate ``numeric_limits::has_denorm``","February 2023","|Complete|","18.0",""
|
||||
"`P2588R3 <https://wg21.link/P2588R3>`__","LWG", "``barrier``’s phase completion guarantees","February 2023","","",""
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -2,7 +2,7 @@
|
||||
"`2994 <https://wg21.link/LWG2994>`__","Needless UB for ``basic_string`` and ``basic_string_view``","Varna June 2023","|Complete|","5.0",""
|
||||
"`3884 <https://wg21.link/LWG3884>`__","``flat_foo`` is missing allocator-extended copy/move constructors","Varna June 2023","","","|flat_containers|"
|
||||
"`3885 <https://wg21.link/LWG3885>`__","``op`` should be in [zombie.names]","Varna June 2023","|Nothing To Do|","",""
|
||||
"`3887 <https://wg21.link/LWG3887>`__","Version macro for ``allocate_at_least``","Varna June 2023","","",""
|
||||
"`3887 <https://wg21.link/LWG3887>`__","Version macro for ``allocate_at_least``","Varna June 2023","|Complete|","19.0",""
|
||||
"`3893 <https://wg21.link/LWG3893>`__","LWG 3661 broke ``atomic<shared_ptr<T>> a; a = nullptr;``","Varna June 2023","","",""
|
||||
"`3894 <https://wg21.link/LWG3894>`__","``generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)`` should not be ``noexcept``","Varna June 2023","","",""
|
||||
"`3903 <https://wg21.link/LWG3903>`__","span destructor is redundantly noexcept","Varna June 2023","|Complete|","7.0",""
|
||||
|
|
@ -20,28 +20,14 @@
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
template <class _Pointer>
|
||||
struct allocation_result {
|
||||
_Pointer ptr;
|
||||
size_t count;
|
||||
};
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
|
||||
|
||||
template <class _Alloc>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<typename allocator_traits<_Alloc>::pointer>
|
||||
allocate_at_least(_Alloc& __alloc, size_t __n) {
|
||||
if constexpr (requires { __alloc.allocate_at_least(__n); }) {
|
||||
return __alloc.allocate_at_least(__n);
|
||||
} else {
|
||||
return {__alloc.allocate(__n), __n};
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Alloc>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto __allocate_at_least(_Alloc& __alloc, size_t __n) {
|
||||
return std::allocate_at_least(__alloc, __n);
|
||||
return std::allocator_traits<_Alloc>::allocate_at_least(__alloc, __n);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <class _Pointer>
|
||||
struct __allocation_result {
|
||||
_Pointer ptr;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <__type_traits/void_t.h>
|
||||
#include <__utility/declval.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
@ -231,6 +232,17 @@ struct __has_select_on_container_copy_construction<
|
||||
|
||||
_LIBCPP_SUPPRESS_DEPRECATED_POP
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
template <class _Pointer, class _SizeType = size_t>
|
||||
struct allocation_result {
|
||||
_Pointer ptr;
|
||||
_SizeType count;
|
||||
};
|
||||
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
|
||||
|
||||
#endif // _LIBCPP_STD_VER
|
||||
|
||||
template <class _Alloc>
|
||||
struct _LIBCPP_TEMPLATE_VIS allocator_traits {
|
||||
using allocator_type = _Alloc;
|
||||
@ -284,6 +296,18 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits {
|
||||
return __a.allocate(__n);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
template <class _Ap = _Alloc>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr allocation_result<pointer, size_type>
|
||||
allocate_at_least(_Ap& __alloc, size_type __n) {
|
||||
if constexpr (requires { __alloc.allocate_at_least(__n); }) {
|
||||
return __alloc.allocate_at_least(__n);
|
||||
} else {
|
||||
return {__alloc.allocate(__n), __n};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
|
||||
deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT {
|
||||
__a.deallocate(__p, __n);
|
||||
|
@ -88,6 +88,9 @@ struct allocator_traits
|
||||
static pointer allocate(allocator_type& a, size_type n); // constexpr and [[nodiscard]] in C++20
|
||||
static pointer allocate(allocator_type& a, size_type n, const_void_pointer hint); // constexpr and [[nodiscard]] in C++20
|
||||
|
||||
[[nodiscard]] static constexpr allocation_result<pointer, size_type>
|
||||
allocate_at_least(Alloc& a, size_type n); // Since C++23
|
||||
|
||||
static void deallocate(allocator_type& a, pointer p, size_type n) noexcept; // constexpr in C++20
|
||||
|
||||
template <class T, class... Args>
|
||||
@ -100,15 +103,11 @@ struct allocator_traits
|
||||
static allocator_type select_on_container_copy_construction(const allocator_type& a); // constexpr in C++20
|
||||
};
|
||||
|
||||
template<class Pointer>
|
||||
template<class Pointer, class SizeType = size_t>
|
||||
struct allocation_result {
|
||||
Pointer ptr;
|
||||
size_t count;
|
||||
}; // since C++23
|
||||
|
||||
template<class Allocator>
|
||||
[[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
|
||||
allocate_at_least(Allocator& a, size_t n); // since C++23
|
||||
SizeType count;
|
||||
}; // Since C++23
|
||||
|
||||
template <>
|
||||
class allocator<void> // removed in C++20
|
||||
|
@ -16,7 +16,7 @@
|
||||
Macro name Value Headers
|
||||
__cpp_lib_adaptor_iterator_pair_constructor 202106L <queue> <stack>
|
||||
__cpp_lib_addressof_constexpr 201603L <memory>
|
||||
__cpp_lib_allocate_at_least 202106L <memory>
|
||||
__cpp_lib_allocate_at_least 202302L <memory>
|
||||
__cpp_lib_allocator_traits_is_always_equal 201411L <deque> <forward_list> <list>
|
||||
<map> <memory> <scoped_allocator>
|
||||
<set> <string> <unordered_map>
|
||||
@ -433,7 +433,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
|
||||
# define __cpp_lib_allocate_at_least 202106L
|
||||
# define __cpp_lib_allocate_at_least 202302L
|
||||
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
|
||||
// # define __cpp_lib_bind_back 202202L
|
||||
# define __cpp_lib_byteswap 202110L
|
||||
|
@ -43,8 +43,6 @@ export namespace std {
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
using std::allocation_result;
|
||||
|
||||
using std::allocate_at_least;
|
||||
#endif
|
||||
|
||||
// [default.allocator], the default allocator
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
/* Constant Value
|
||||
__cpp_lib_addressof_constexpr 201603L [C++17]
|
||||
__cpp_lib_allocate_at_least 202106L [C++23]
|
||||
__cpp_lib_allocate_at_least 202302L [C++23]
|
||||
__cpp_lib_allocator_traits_is_always_equal 201411L [C++17]
|
||||
__cpp_lib_assume_aligned 201811L [C++20]
|
||||
__cpp_lib_atomic_value_initialization 201911L [C++20]
|
||||
@ -432,8 +432,8 @@
|
||||
# ifndef __cpp_lib_allocate_at_least
|
||||
# error "__cpp_lib_allocate_at_least should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_allocate_at_least != 202106L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202106L in c++23"
|
||||
# if __cpp_lib_allocate_at_least != 202302L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202302L in c++23"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_allocator_traits_is_always_equal
|
||||
@ -569,8 +569,8 @@
|
||||
# ifndef __cpp_lib_allocate_at_least
|
||||
# error "__cpp_lib_allocate_at_least should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_allocate_at_least != 202106L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202106L in c++26"
|
||||
# if __cpp_lib_allocate_at_least != 202302L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202302L in c++26"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_allocator_traits_is_always_equal
|
||||
|
@ -18,7 +18,7 @@
|
||||
/* Constant Value
|
||||
__cpp_lib_adaptor_iterator_pair_constructor 202106L [C++23]
|
||||
__cpp_lib_addressof_constexpr 201603L [C++17]
|
||||
__cpp_lib_allocate_at_least 202106L [C++23]
|
||||
__cpp_lib_allocate_at_least 202302L [C++23]
|
||||
__cpp_lib_allocator_traits_is_always_equal 201411L [C++17]
|
||||
__cpp_lib_any 201606L [C++17]
|
||||
__cpp_lib_apply 201603L [C++17]
|
||||
@ -4279,8 +4279,8 @@
|
||||
# ifndef __cpp_lib_allocate_at_least
|
||||
# error "__cpp_lib_allocate_at_least should be defined in c++23"
|
||||
# endif
|
||||
# if __cpp_lib_allocate_at_least != 202106L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202106L in c++23"
|
||||
# if __cpp_lib_allocate_at_least != 202302L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202302L in c++23"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_allocator_traits_is_always_equal
|
||||
@ -5846,8 +5846,8 @@
|
||||
# ifndef __cpp_lib_allocate_at_least
|
||||
# error "__cpp_lib_allocate_at_least should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_allocate_at_least != 202106L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202106L in c++26"
|
||||
# if __cpp_lib_allocate_at_least != 202302L
|
||||
# error "__cpp_lib_allocate_at_least should have the value 202302L in c++26"
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_allocator_traits_is_always_equal
|
||||
|
@ -39,22 +39,22 @@ struct has_allocate_at_least {
|
||||
|
||||
constexpr T* allocate(std::size_t) { return &t1; }
|
||||
constexpr void deallocate(T*, std::size_t) {}
|
||||
constexpr std::allocation_result<T*> allocate_at_least(std::size_t) {
|
||||
return {&t2, 2};
|
||||
}
|
||||
constexpr std::allocation_result<T*> allocate_at_least(std::size_t) { return {&t2, 2}; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
{ // check that std::allocate_at_least forwards to allocator::allocate if no allocate_at_least exists
|
||||
no_allocate_at_least<int> alloc;
|
||||
std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
|
||||
std::same_as<std::allocation_result<int*>> decltype(auto) ret =
|
||||
std::allocator_traits<decltype(alloc)>::allocate_at_least(alloc, 1);
|
||||
assert(ret.count == 1);
|
||||
assert(ret.ptr == &alloc.t);
|
||||
}
|
||||
|
||||
{ // check that std::allocate_at_least forwards to allocator::allocate_at_least if allocate_at_least exists
|
||||
has_allocate_at_least<int> alloc;
|
||||
std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
|
||||
std::same_as<std::allocation_result<int*>> decltype(auto) ret =
|
||||
std::allocator_traits<decltype(alloc)>::allocate_at_least(alloc, 1);
|
||||
assert(ret.count == 2);
|
||||
assert(ret.ptr == &alloc.t2);
|
||||
}
|
@ -88,9 +88,8 @@ feature_test_macros = [
|
||||
{
|
||||
"name": "__cpp_lib_allocate_at_least",
|
||||
"values": {
|
||||
"c++23": 202106,
|
||||
# Note LWG3887 Version macro for allocate_at_least
|
||||
# "c++26": 202302, # P2652R2 Disallow User Specialization of allocator_traits
|
||||
"c++23": 202302, # P2652R2 Disallow User Specialization of allocator_traits
|
||||
},
|
||||
"headers": ["memory"],
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user