Skip to content

[libc++] Simplify unique_ptr constructor SFINAE#201305

Merged
philnik777 merged 1 commit into
llvm:mainfrom
philnik777:simplify_uniuqe_ptr_sfinae
Jun 4, 2026
Merged

[libc++] Simplify unique_ptr constructor SFINAE#201305
philnik777 merged 1 commit into
llvm:mainfrom
philnik777:simplify_uniuqe_ptr_sfinae

Conversation

@philnik777
Copy link
Copy Markdown
Contributor

This patch does a couple of things:

  • inline aliases to __enable_if_ts, making it easier to understand what's actually going on
  • make the enable_ifs dependent via a class _Deleter = deleter_type instead of a bool and __dependent_type, reducing the number of instantiated classes
  • remove __unique_ptr_deleter_sfinae

@philnik777 philnik777 marked this pull request as ready for review June 3, 2026 13:17
@philnik777 philnik777 requested a review from a team as a code owner June 3, 2026 13:17
@llvmorg-github-actions llvmorg-github-actions Bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 3, 2026
@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This patch does a couple of things:

  • inline aliases to __enable_if_ts, making it easier to understand what's actually going on
  • make the enable_ifs dependent via a class _Deleter = deleter_type instead of a bool and __dependent_type, reducing the number of instantiated classes
  • remove __unique_ptr_deleter_sfinae

Full diff: https://github.com/llvm/llvm-project/pull/201305.diff

1 Files Affected:

  • (modified) libcxx/include/__memory/unique_ptr.h (+46-109)
diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 8fba2a4a1509d..32f9459f9fc2c 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -27,7 +27,6 @@
 #include <__type_traits/add_reference.h>
 #include <__type_traits/common_type.h>
 #include <__type_traits/conditional.h>
-#include <__type_traits/dependent_type.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_array.h>
@@ -43,7 +42,7 @@
 #include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/remove_extent.h>
-#include <__type_traits/type_identity.h>
+#include <__type_traits/remove_reference.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
@@ -95,28 +94,6 @@ inline const bool __is_default_deleter_v = false;
 template <class _Tp>
 inline const bool __is_default_deleter_v<default_delete<_Tp> > = true;
 
-template <class _Deleter>
-struct __unique_ptr_deleter_sfinae {
-  static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
-  typedef const _Deleter& __lval_ref_type;
-  typedef _Deleter&& __good_rval_ref_type;
-  typedef true_type __enable_rval_overload;
-};
-
-template <class _Deleter>
-struct __unique_ptr_deleter_sfinae<_Deleter const&> {
-  typedef const _Deleter& __lval_ref_type;
-  typedef const _Deleter&& __bad_rval_ref_type;
-  typedef false_type __enable_rval_overload;
-};
-
-template <class _Deleter>
-struct __unique_ptr_deleter_sfinae<_Deleter&> {
-  typedef _Deleter& __lval_ref_type;
-  typedef _Deleter&& __bad_rval_ref_type;
-  typedef false_type __enable_rval_overload;
-};
-
 template <class, class = void>
 inline const bool __can_dereference = false;
 
@@ -152,24 +129,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
 private:
   _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
 
-  using _DeleterSFINAE _LIBCPP_NODEBUG = __unique_ptr_deleter_sfinae<_Dp>;
-
-  template <bool _Dummy>
-  using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
-
-  template <bool _Dummy>
-  using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
-
-  template <bool _Dummy>
-  using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
-
-  template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
-  using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
-      __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
-
-  template <class _ArgType>
-  using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
-
   template <class _UPtr, class _Up>
   using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
       __enable_if_t< is_convertible<typename _UPtr::pointer, pointer>::value && !is_array<_Up>::value >;
@@ -183,31 +142,33 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
   using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
 
 public:
-  template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
+  template <class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
+  template <class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
+  template <class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT
       : __ptr_(__p),
         __deleter_() {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT
+  template <class _Deleter = deleter_type, __enable_if_t<is_copy_constructible<_Deleter>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, const deleter_type& __d) _NOEXCEPT
       : __ptr_(__p),
         __deleter_(__d) {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
+  template <class _Deleter                                                                               = deleter_type,
+            __enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, deleter_type&& __d) _NOEXCEPT
       : __ptr_(__p),
-        __deleter_(std::move(__d)) {
-    static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-  }
+        __deleter_(std::move(__d)) {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > >
-  _LIBCPP_HIDE_FROM_ABI unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
+  template <class _Deleter = deleter_type, __enable_if_t<is_reference<_Deleter>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI unique_ptr(pointer, __libcpp_remove_reference_t<deleter_type>&&) = delete;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
       : __ptr_(__u.release()),
@@ -441,27 +402,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
                               (is_same<pointer, element_type*>::value &&
                                is_convertible<_FromElem (*)[], element_type (*)[]>::value) > {};
 
-  typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
-
-  template <bool _Dummy>
-  using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
-
-  template <bool _Dummy>
-  using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
-
-  template <bool _Dummy>
-  using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
-
-  template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
-  using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
-      __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
-
-  template <class _ArgType>
-  using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
-
-  template <class _Pp>
-  using _EnableIfPointerConvertible _LIBCPP_NODEBUG = __enable_if_t< _CheckArrayPointerConversion<_Pp>::value >;
-
   template <class _UPtr, class _Up, class _ElemT = typename _UPtr::element_type>
   using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
       __enable_if_t< is_array<_Up>::value && is_same<pointer, element_type*>::value &&
@@ -477,17 +417,19 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
   using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
 
 public:
-  template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
+  template <class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
+  template <class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
 
-  template <class _Pp,
-            bool _Dummy = true,
-            class       = _EnableIfDeleterDefaultConstructible<_Dummy>,
-            class       = _EnableIfPointerConvertible<_Pp> >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __ptr) _NOEXCEPT
+  template <class _Ptr,
+            class _Deleter = deleter_type,
+            __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0,
+            __enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int>                                 = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Ptr __ptr) _NOEXCEPT
       : __ptr_(__ptr),
         __deleter_() {}
 
@@ -497,43 +439,38 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
       : __ptr_(__ptr),
         __checker_(__size) {}
 
-  template <class _Pp,
-            bool _Dummy = true,
-            class       = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
-            class       = _EnableIfPointerConvertible<_Pp> >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __ptr, _LValRefType<_Dummy> __deleter) _NOEXCEPT
+  template <class _Ptr,
+            class _Deleter                                                = deleter_type,
+            __enable_if_t<is_copy_constructible<_Deleter>::value, int>    = 0,
+            __enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Ptr __ptr, const deleter_type& __deleter) _NOEXCEPT
       : __ptr_(__ptr),
         __deleter_(__deleter) {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _LValRefType<_Dummy> __deleter) _NOEXCEPT
+  template <class _Deleter = deleter_type, __enable_if_t<is_copy_constructible<_Deleter>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, const deleter_type& __deleter) _NOEXCEPT
       : __ptr_(nullptr),
         __deleter_(__deleter) {}
 
-  template <class _Pp,
-            bool _Dummy = true,
-            class       = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >,
-            class       = _EnableIfPointerConvertible<_Pp> >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
-  unique_ptr(_Pp __ptr, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
+  template <class _Ptr,
+            class _Deleter                                                                               = deleter_type,
+            __enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0,
+            __enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int>                                = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Ptr __ptr, deleter_type&& __deleter) _NOEXCEPT
       : __ptr_(__ptr),
-        __deleter_(std::move(__deleter)) {
-    static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-  }
+        __deleter_(std::move(__deleter)) {}
 
-  template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
-  unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
+  template <class _Deleter                                                                               = deleter_type,
+            __enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, deleter_type&& __deleter) _NOEXCEPT
       : __ptr_(nullptr),
-        __deleter_(std::move(__deleter)) {
-    static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
-  }
+        __deleter_(std::move(__deleter)) {}
 
-  template <class _Pp,
-            bool _Dummy = true,
-            class       = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >,
-            class       = _EnableIfPointerConvertible<_Pp> >
-  _LIBCPP_HIDE_FROM_ABI unique_ptr(_Pp __ptr, _BadRValRefType<_Dummy> __deleter) = delete;
+  template <class _Ptr,
+            class _Deleter                                                = deleter_type,
+            __enable_if_t<is_reference<_Deleter>::value, int>             = 0,
+            __enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI unique_ptr(_Ptr, __libcpp_remove_reference_t<deleter_type>&&) = delete;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
       : __ptr_(__u.release()),

@philnik777 philnik777 self-assigned this Jun 3, 2026
@philnik777 philnik777 merged commit c88cefb into llvm:main Jun 4, 2026
84 checks passed
@philnik777 philnik777 deleted the simplify_uniuqe_ptr_sfinae branch June 4, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants