[libcxx-commits] [libcxx] [libc++] Remove _LIBCPP_COMPRESSED_PAIR/TRIPLE from shared_ptr (PR #200401)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat May 30 23:37:13 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
---
Patch is 26.53 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/200401.diff
6 Files Affected:
- (modified) libcxx/docs/ABIGuarantees.rst (+1-1)
- (modified) libcxx/include/__configuration/attributes.h (+2)
- (modified) libcxx/include/__memory/compressed_pair.h (-25)
- (modified) libcxx/include/__memory/shared_ptr.h (+57-82)
- (removed) libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp (-232)
- (modified) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.lwg2070.pass.cpp (+17-8)
``````````diff
diff --git a/libcxx/docs/ABIGuarantees.rst b/libcxx/docs/ABIGuarantees.rst
index 4bd9737542a43..87ba69401c7ad 100644
--- a/libcxx/docs/ABIGuarantees.rst
+++ b/libcxx/docs/ABIGuarantees.rst
@@ -67,7 +67,7 @@ removes these workarounds for platforms that don't care about ABI compatibility.
``_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING``
------------------------------------------
-This removes artificial padding from ``_LIBCPP_COMPRESSED_PAIR`` and ``_LIBCPP_COMPRESSED_TRIPLE``.
+This removes artificial padding from ``_LIBCPP_COMPRESSED_PAIR``.
These macros are used inside the associative and unordered containers, ``deque``, ``forward_list``, ``future``,
``list``, ``basic_string``, ``function``, ``shared_ptr``, ``unique_ptr``, and ``vector`` to stay ABI compatible with the
diff --git a/libcxx/include/__configuration/attributes.h b/libcxx/include/__configuration/attributes.h
index cc828466482fd..71ab098e20744 100644
--- a/libcxx/include/__configuration/attributes.h
+++ b/libcxx/include/__configuration/attributes.h
@@ -215,6 +215,8 @@
#endif
#define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
+#define _LIBCPP_HIDE_STRUCT_FROM_ABI [[__gnu__::__abi_tag__(_LIBCPP_TOSTRING(_LIBCPP_ODR_SIGNATURE))]]
+
// Optional attributes
// -------------------
diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h
index f1f1c920453cf..bb745620b9f85 100644
--- a/libcxx/include/__memory/compressed_pair.h
+++ b/libcxx/include/__memory/compressed_pair.h
@@ -94,16 +94,6 @@ class __compressed_pair_padding<_ToPad, true> {};
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _)
-
-# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
- _LIBCPP_NO_UNIQUE_ADDRESS \
- __attribute__((__aligned__(::std::__compressed_pair_alignment<T2>), \
- __aligned__(::std::__compressed_pair_alignment<T3>))) T1 Initializer1; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
- _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
- _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _)
# else
# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
struct { \
@@ -112,16 +102,6 @@ class __compressed_pair_padding<_ToPad, true> {};
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
}
-
-# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
- struct { \
- _LIBCPP_NO_UNIQUE_ADDRESS T1 Initializer1; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
- _LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
- _LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
- _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _); \
- }
# endif
#else
@@ -130,11 +110,6 @@ class __compressed_pair_padding<_ToPad, true> {};
# define _LIBCPP_COMPRESSED_PAIR(T1, Name1, T2, Name2) \
_LIBCPP_NO_UNIQUE_ADDRESS T1 Name1; \
_LIBCPP_NO_UNIQUE_ADDRESS T2 Name2
-
-# define _LIBCPP_COMPRESSED_TRIPLE(T1, Name1, T2, Name2, T3, Name3) \
- _LIBCPP_NO_UNIQUE_ADDRESS T1 Name1; \
- _LIBCPP_NO_UNIQUE_ADDRESS T2 Name2; \
- _LIBCPP_NO_UNIQUE_ADDRESS T3 Name3
#endif // _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 66442c8868005..6cdfd0b55fdf5 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -27,7 +27,6 @@
#include <__memory/allocator_destructor.h>
#include <__memory/allocator_traits.h>
#include <__memory/auto_ptr.h>
-#include <__memory/compressed_pair.h>
#include <__memory/construct_at.h>
#include <__memory/destroy.h>
#include <__memory/pointer_traits.h>
@@ -36,18 +35,13 @@
#include <__memory/unique_ptr.h>
#include <__type_traits/add_reference.h>
#include <__type_traits/conditional.h>
-#include <__type_traits/conjunction.h>
-#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
-#include <__type_traits/integral_constant.h>
#include <__type_traits/is_array.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_function.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/is_same.h>
-#include <__type_traits/nat.h>
-#include <__type_traits/negation.h>
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_extent.h>
#include <__type_traits/remove_reference.h>
@@ -94,12 +88,16 @@ template <class _Tp>
class weak_ptr;
template <class _Tp, class _Dp, class _Alloc>
-class __shared_ptr_pointer : public __shared_weak_count {
- _LIBCPP_COMPRESSED_TRIPLE(_Tp, __ptr_, _Dp, __deleter_, _Alloc, __alloc_);
+class _LIBCPP_HIDE_STRUCT_FROM_ABI __shared_ptr_pointer final : public __shared_weak_count {
+ using __alloc_t = __allocator_traits_rebind_t<_Alloc, __shared_ptr_pointer>;
+
+ _LIBCPP_NO_UNIQUE_ADDRESS __alloc_t __alloc_;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Dp __deleter_;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Tp __ptr_;
public:
_LIBCPP_HIDE_FROM_ABI __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a)
- : __ptr_(__p), __deleter_(std::move(__d)), __alloc_(std::move(__a)) {}
+ : __alloc_(std::move(__a)), __deleter_(std::move(__d)), __ptr_(__p) {}
#if _LIBCPP_HAS_RTTI
_LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* __get_deleter(const type_info& __t) const _NOEXCEPT override {
@@ -110,17 +108,14 @@ class __shared_ptr_pointer : public __shared_weak_count {
private:
_LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override {
__deleter_(__ptr_);
+ __ptr_.~_Tp();
__deleter_.~_Dp();
}
_LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
- typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _Al;
- typedef allocator_traits<_Al> _ATraits;
- typedef pointer_traits<typename _ATraits::pointer> _PTraits;
-
- _Al __a(__alloc_);
- __alloc_.~_Alloc();
- __a.deallocate(_PTraits::pointer_to(*this), 1);
+ __alloc_t __a(__alloc_);
+ __alloc_.~__alloc_t();
+ __a.deallocate(pointer_traits<typename allocator_traits<__alloc_t>::pointer>::pointer_to(*this), 1);
}
};
@@ -130,79 +125,53 @@ class __shared_ptr_pointer : public __shared_weak_count {
struct __for_overwrite_tag {};
template <class _Tp, class _Alloc>
-struct __shared_ptr_emplace : __shared_weak_count {
+struct _LIBCPP_HIDE_STRUCT_FROM_ABI __shared_ptr_emplace : __shared_weak_count {
+ using __alloc_t _LIBCPP_NODEBUG = __allocator_traits_rebind_t<_Alloc, __shared_ptr_emplace>;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_t>;
using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>;
- template <class... _Args,
- class _Allocator = _Alloc,
- __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) {
- static_assert(
- sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
- ::new (static_cast<void*>(__get_elem())) __value_type;
+ template <class... _Args>
+ _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __alloc_(std::move(__a)) {
+ __alloc_traits::construct(__alloc_, __get_elem(), std::forward<_Args>(__args)...);
}
- template <class... _Args,
- class _Allocator = _Alloc,
- __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) {
- using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __value_type>::type;
- _TpAlloc __tmp(*__get_alloc());
- allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...);
- }
-
- _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); }
-
- _LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
+ _LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return reinterpret_cast<__value_type*>(__buffer_); }
private:
- template <class _Allocator = _Alloc,
- __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
- __get_elem()->~__value_type();
- }
-
- template <class _Allocator = _Alloc,
- __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
- using _TpAlloc = typename __allocator_traits_rebind<_Allocator, __remove_cv_t<_Tp> >::type;
- _TpAlloc __tmp(*__get_alloc());
- allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override {
+ __alloc_traits::destroy(__alloc_, __get_elem());
}
- _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { __on_zero_shared_impl(); }
-
_LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
- using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type;
- using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer;
- _ControlBlockAlloc __tmp(*__get_alloc());
- __storage_.~_Storage();
- allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1);
+ __alloc_t __tmp(__alloc_);
+ __alloc_.~__alloc_t();
+ __alloc_traits::deallocate(__tmp, pointer_traits<typename __alloc_traits::pointer>::pointer_to(*this), 1);
}
- // TODO: It should be possible to refactor this to remove `_Storage` entirely.
- // This class implements the control block for non-array shared pointers created
- // through `std::allocate_shared` and `std::make_shared`.
- struct _Storage {
- struct _Data {
- _LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, __value_type, __elem_);
- };
+ _LIBCPP_NO_UNIQUE_ADDRESS __alloc_t __alloc_;
+ _ALIGNAS_TYPE(__value_type) char __buffer_[sizeof(__value_type)];
+};
- _ALIGNAS_TYPE(_Data) char __buffer_[sizeof(_Data)];
+template <class _Tp, class _Alloc>
+struct _LIBCPP_HIDE_STRUCT_FROM_ABI __shared_ptr_emplace_for_overwrite : __shared_weak_count {
+ using __alloc_t _LIBCPP_NODEBUG = __allocator_traits_rebind_t<_Alloc, __shared_ptr_emplace_for_overwrite>;
+ using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>;
- _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { ::new ((void*)__get_alloc()) _Alloc(std::move(__a)); }
- _LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); }
+ explicit __shared_ptr_emplace_for_overwrite(_Alloc __a) : __alloc_(std::move(__a)) {}
- _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT {
- return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__alloc_);
- }
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { __value_.~__value_type(); }
+ _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
+ __alloc_t __tmp(__alloc_);
+ __alloc_.~__alloc_t();
+ using __alloc_traits = allocator_traits<__alloc_t>;
+ __alloc_traits::deallocate(__tmp, pointer_traits<typename __alloc_traits::pointer>::pointer_to(*this), 1);
+ }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI __value_type* __get_elem() _NOEXCEPT {
- return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__elem_);
- }
- };
+ __value_type* __get_elem() _NOEXCEPT { return std::addressof(__value_); }
- _Storage __storage_;
+private:
+ _LIBCPP_NO_UNIQUE_ADDRESS __alloc_t __alloc_;
+ _LIBCPP_NO_UNIQUE_ADDRESS __value_type __value_;
};
struct __shared_ptr_dummy_rebind_allocator_type;
@@ -654,15 +623,21 @@ shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>;
//
// std::allocate_shared and std::make_shared
//
-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, _Alloc>;
+
+template <class _ControlBlock, class _Tp, class _Alloc, class... _Args>
+_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> __allocate_shared_impl(const _Alloc& __alloc, _Args&&... __args) {
using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type;
- __allocation_guard<_ControlBlockAllocator> __guard(__a, 1);
- ::new ((void*)std::addressof(*__guard.__get())) _ControlBlock(__a, std::forward<_Args>(__args)...);
+ __allocation_guard<_ControlBlockAllocator> __guard(__alloc, 1);
+ ::new ((void*)std::addressof(*__guard.__get())) _ControlBlock(__alloc, std::forward<_Args>(__args)...);
auto __control_block = __guard.__release_ptr();
return shared_ptr<_Tp>::__create_with_control_block(
- (*__control_block).__get_elem(), std::addressof(*__control_block));
+ __control_block->__get_elem(), std::__to_address(__control_block));
+}
+
+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, __args...);
}
template <class _Tp, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0>
@@ -674,9 +649,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 _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
- _ForOverwriteAllocator __alloc(__a);
- return std::allocate_shared<_Tp>(__alloc);
+ 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);
}
template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0>
diff --git a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp b/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp
deleted file mode 100644
index 9cb5b2ffbae97..0000000000000
--- a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
-
-// This test makes sure that the control block implementation used for non-array
-// types in std::make_shared and std::allocate_shared is ABI compatible with the
-// original implementation.
-//
-// This test is relevant because the implementation of that control block is
-// different starting in C++20, a change that was required to implement P0674.
-
-#include <cassert>
-#include <cstddef>
-#include <memory>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-#include <string>
-#include <vector>
-
-#include "test_macros.h"
-
-struct value_init_tag {};
-
-template <class T, int _Idx, bool CanBeEmptyBase = std::is_empty<T>::value && !std::__is_final_v<T>>
-struct compressed_pair_elem {
- explicit compressed_pair_elem(value_init_tag) : value_() {}
-
- template <class U>
- explicit compressed_pair_elem(U&& u) : value_(std::forward<U>(u)) {}
-
- T& get() { return value_; }
-
-private:
- T value_;
-};
-
-template <class T, int _Idx>
-struct compressed_pair_elem<T, _Idx, true> : private T {
- explicit compressed_pair_elem(value_init_tag) : T() {}
-
- template <class U>
- explicit compressed_pair_elem(U&& u) : T(std::forward<U>(u)) {}
-
- T& get() { return *this; }
-};
-
-template <class T1, class T2>
-class compressed_pair : private compressed_pair_elem<T1, 0>, private compressed_pair_elem<T2, 1> {
-public:
- using Base1 = compressed_pair_elem<T1, 0>;
- using Base2 = compressed_pair_elem<T2, 1>;
-
- template <class U1, class U2>
- explicit compressed_pair(U1&& t1, U2&& t2) : Base1(std::forward<U1>(t1)), Base2(std::forward<U2>(t2)) {}
-
- T1& first() { return static_cast<Base1&>(*this).get(); }
- T2& second() { return static_cast<Base2&>(*this).get(); }
-};
-
-// This is the pre-C++20 implementation of the control block used by non-array
-// std::allocate_shared and std::make_shared. We keep it here so that we can
-// make sure our implementation is backwards compatible with it forever.
-//
-// Of course, the class and its methods were renamed, but the size and layout
-// of the class should remain the same as the original implementation.
-template <class T, class Alloc>
-struct OldEmplaceControlBlock : std::__shared_weak_count {
- explicit OldEmplaceControlBlock(Alloc a) : data_(std::move(a), value_init_tag()) {}
- T* get_elem() noexcept { return std::addressof(data_.second()); }
- Alloc* get_alloc() noexcept { return std::addressof(data_.first()); }
-
-private:
- virtual void __on_zero_shared() noexcept {
- // Not implemented
- }
-
- virtual void __on_zero_shared_weak() n...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/200401
More information about the libcxx-commits
mailing list