[libcxx-commits] [libcxx] [libc++][NFC] Use `if constexpr` instead of SFINAE to simplify shared_ptr (PR #113495)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 24 07:25:41 PDT 2024
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/113495
>From b66bb69a781c54dc35651aa9a43d4c9708f7620a Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 14 Sep 2023 15:07:34 -0400
Subject: [PATCH 1/2] [libc++][NFC] Use `if constexpr` instead of SFINAE to
simplify shared_ptr
Since we can use `if constexpr` in all standard modes (it is supported
as a compiler extension), we can simplify the implementation of
__shared_ptr_emplace.
---
libcxx/include/__memory/shared_ptr.h | 47 +++++++++++-----------------
1 file changed, 18 insertions(+), 29 deletions(-)
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 65870ba574c25b..080ced077b7338 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -252,22 +252,17 @@ template <class _Tp, class _Alloc>
struct __shared_ptr_emplace : __shared_weak_count {
using __value_type = __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>
+ template <class... _Args>
_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,
- 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)...);
+ if constexpr (is_same<typename _Alloc::value_type, __for_overwrite_tag>::value) {
+ 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;
+ } else {
+ 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(); }
@@ -275,22 +270,16 @@ struct __shared_ptr_emplace : __shared_weak_count {
_LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
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 {
+ if constexpr (is_same<typename _Alloc::value_type, __for_overwrite_tag>::value) {
+ __get_elem()->~__value_type();
+ } else {
+ using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __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 { __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;
>From 97c42fed7eab49022793337983f97d96709906a0 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 24 Oct 2024 10:25:29 -0400
Subject: [PATCH 2/2] Fix obvious typo
---
libcxx/include/__memory/shared_ptr.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 080ced077b7338..85abd0f10a71b6 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -253,7 +253,7 @@ struct __shared_ptr_emplace : __shared_weak_count {
using __value_type = __remove_cv_t<_Tp>;
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) {
+ _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) {
if constexpr (is_same<typename _Alloc::value_type, __for_overwrite_tag>::value) {
static_assert(
sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
More information about the libcxx-commits
mailing list