[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