[libc++] Fix shared_ptr not accepting allocators with explicit conversions (#208439)

Allocators are only required to be explicitly convertible between
different types. `shared_ptr` currently requires implicit conversions,
however.

This is a regression introduced by #200401.
This commit is contained in:
Nikolas Klauser authored and GitHub committed 2026-07-10 15:31:02 +02:00
1 parent 9a1fe8e03c
commit 62bf9d924c
2 files changed
+12 -11

No files matched your search

+6 -5
View File
@@ -658,8 +658,9 @@ _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> __allocate_shared_impl(const _Alloc& __all
template <class _Tp, class _Alloc, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&&... __args) {
using _ControlBlock = __shared_ptr_emplace<_Tp, __allocator_traits_rebind_t<_Alloc, __remove_cv_t<_Tp> > >;
return std::__allocate_shared_impl<_ControlBlock, _Tp>(__a, std::forward<_Args>(__args)...);
using _CanonicalAlloc = __allocator_traits_rebind_t<_Alloc, __remove_cv_t<_Tp> >;
using _ControlBlock = __shared_ptr_emplace<_Tp, _CanonicalAlloc>;
return std::__allocate_shared_impl<_ControlBlock, _Tp>(_CanonicalAlloc(__a), std::forward<_Args>(__args)...);
}
template <class _Tp, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0>
@@ -671,9 +672,9 @@ template <class _Tp, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> =
template <class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) {
using _ControlBlock =
__shared_ptr_emplace_for_overwrite<_Tp, __allocator_traits_rebind_t<_Alloc, __remove_cv_t<_Tp>>>;
return std::__allocate_shared_impl<_ControlBlock, _Tp>(__a);
using _CanonicalAlloc = __allocator_traits_rebind_t<_Alloc, remove_cv_t<_Tp>>;
using _ControlBlock = __shared_ptr_emplace_for_overwrite<_Tp, _CanonicalAlloc>;
return std::__allocate_shared_impl<_ControlBlock, _Tp>(_CanonicalAlloc(__a));
}
template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0>
+6 -6
View File
@@ -29,7 +29,7 @@ public:
bare_allocator() TEST_NOEXCEPT {}
template <class U>
bare_allocator(bare_allocator<U>) TEST_NOEXCEPT {}
explicit bare_allocator(bare_allocator<U>) TEST_NOEXCEPT {}
T* allocate(std::size_t n) { return static_cast<T*>(::operator new(n * sizeof(T))); }
@@ -59,7 +59,7 @@ public:
typedef T value_type;
template <class U>
TEST_CONSTEXPR_CXX20 no_default_allocator(no_default_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 explicit no_default_allocator(no_default_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return static_cast<T*>(std::allocator<T>().allocate(n)); }
@@ -102,7 +102,7 @@ public:
malloc_allocator() TEST_NOEXCEPT { assert(!disable_default_constructor); }
template <class U>
malloc_allocator(malloc_allocator<U>) TEST_NOEXCEPT {}
explicit malloc_allocator(malloc_allocator<U>) TEST_NOEXCEPT {}
T* allocate(std::size_t n) {
const std::size_t nbytes = n * sizeof(T);
@@ -410,7 +410,7 @@ public:
TEST_CONSTEXPR_CXX20 complete_type_allocator() TEST_NOEXCEPT {}
template <class U>
TEST_CONSTEXPR_CXX20 complete_type_allocator(complete_type_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 explicit complete_type_allocator(complete_type_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) { return static_cast<T*>(std::allocator<T>().allocate(n)); }
@@ -466,7 +466,7 @@ public:
TEST_CONSTEXPR_CXX20 safe_allocator() TEST_NOEXCEPT {}
template <class U>
TEST_CONSTEXPR_CXX20 safe_allocator(safe_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 explicit safe_allocator(safe_allocator<U>) TEST_NOEXCEPT {}
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) {
T* memory = std::allocator<T>().allocate(n);
@@ -499,7 +499,7 @@ struct tiny_size_allocator {
tiny_size_allocator() = default;
template <class U>
TEST_CONSTEXPR_CXX20 tiny_size_allocator(tiny_size_allocator<MaxSize, U>) {}
TEST_CONSTEXPR_CXX20 explicit tiny_size_allocator(tiny_size_allocator<MaxSize, U>) {}
TEST_CONSTEXPR_CXX20 T* allocate(std::size_t n) {
assert(n <= MaxSize);