[libcxx-commits] [libcxx] [libc++] Simplify unique_ptr constructor SFINAE (PR #201305)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jun 3 03:12:48 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/201305
This patch does a couple of things:
- inline aliases to `__enable_if_t`s, making it easier to understand what's actually going on
- make the `enable_if`s 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`
>From d6812495f22b14771d057a5900373bab66bbf680 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 3 Jun 2026 12:06:36 +0200
Subject: [PATCH] [libc++] Simplify unique_ptr constructor SFINAE
---
libcxx/include/__memory/unique_ptr.h | 155 ++++++++-------------------
1 file changed, 46 insertions(+), 109 deletions(-)
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()),
More information about the libcxx-commits
mailing list