Skip to content

Commit c88cefb

Browse files
authored
[libc++] Simplify unique_ptr constructor SFINAE (#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`
1 parent 3112581 commit c88cefb

1 file changed

Lines changed: 46 additions & 109 deletions

File tree

libcxx/include/__memory/unique_ptr.h

Lines changed: 46 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <__type_traits/add_reference.h>
2828
#include <__type_traits/common_type.h>
2929
#include <__type_traits/conditional.h>
30-
#include <__type_traits/dependent_type.h>
3130
#include <__type_traits/enable_if.h>
3231
#include <__type_traits/integral_constant.h>
3332
#include <__type_traits/is_array.h>
@@ -43,7 +42,7 @@
4342
#include <__type_traits/is_trivially_relocatable.h>
4443
#include <__type_traits/is_void.h>
4544
#include <__type_traits/remove_extent.h>
46-
#include <__type_traits/type_identity.h>
45+
#include <__type_traits/remove_reference.h>
4746
#include <__utility/declval.h>
4847
#include <__utility/forward.h>
4948
#include <__utility/move.h>
@@ -95,28 +94,6 @@ inline const bool __is_default_deleter_v = false;
9594
template <class _Tp>
9695
inline const bool __is_default_deleter_v<default_delete<_Tp> > = true;
9796

98-
template <class _Deleter>
99-
struct __unique_ptr_deleter_sfinae {
100-
static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
101-
typedef const _Deleter& __lval_ref_type;
102-
typedef _Deleter&& __good_rval_ref_type;
103-
typedef true_type __enable_rval_overload;
104-
};
105-
106-
template <class _Deleter>
107-
struct __unique_ptr_deleter_sfinae<_Deleter const&> {
108-
typedef const _Deleter& __lval_ref_type;
109-
typedef const _Deleter&& __bad_rval_ref_type;
110-
typedef false_type __enable_rval_overload;
111-
};
112-
113-
template <class _Deleter>
114-
struct __unique_ptr_deleter_sfinae<_Deleter&> {
115-
typedef _Deleter& __lval_ref_type;
116-
typedef _Deleter&& __bad_rval_ref_type;
117-
typedef false_type __enable_rval_overload;
118-
};
119-
12097
template <class, class = void>
12198
inline const bool __can_dereference = false;
12299

@@ -152,24 +129,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr {
152129
private:
153130
_LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
154131

155-
using _DeleterSFINAE _LIBCPP_NODEBUG = __unique_ptr_deleter_sfinae<_Dp>;
156-
157-
template <bool _Dummy>
158-
using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
159-
160-
template <bool _Dummy>
161-
using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
162-
163-
template <bool _Dummy>
164-
using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
165-
166-
template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
167-
using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
168-
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
169-
170-
template <class _ArgType>
171-
using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
172-
173132
template <class _UPtr, class _Up>
174133
using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
175134
__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 {
183142
using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
184143

185144
public:
186-
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
145+
template <class _Deleter = deleter_type,
146+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
187147
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
188148

189-
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
149+
template <class _Deleter = deleter_type,
150+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
190151
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
191152

192-
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
153+
template <class _Deleter = deleter_type,
154+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
193155
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT
194156
: __ptr_(__p),
195157
__deleter_() {}
196158

197-
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
198-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT
159+
template <class _Deleter = deleter_type, __enable_if_t<is_copy_constructible<_Deleter>::value, int> = 0>
160+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, const deleter_type& __d) _NOEXCEPT
199161
: __ptr_(__p),
200162
__deleter_(__d) {}
201163

202-
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
203-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
164+
template <class _Deleter = deleter_type,
165+
__enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0>
166+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, deleter_type&& __d) _NOEXCEPT
204167
: __ptr_(__p),
205-
__deleter_(std::move(__d)) {
206-
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
207-
}
168+
__deleter_(std::move(__d)) {}
208169

209-
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > >
210-
_LIBCPP_HIDE_FROM_ABI unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
170+
template <class _Deleter = deleter_type, __enable_if_t<is_reference<_Deleter>::value, int> = 0>
171+
_LIBCPP_HIDE_FROM_ABI unique_ptr(pointer, __libcpp_remove_reference_t<deleter_type>&&) = delete;
211172

212173
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
213174
: __ptr_(__u.release()),
@@ -441,27 +402,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
441402
(is_same<pointer, element_type*>::value &&
442403
is_convertible<_FromElem (*)[], element_type (*)[]>::value) > {};
443404

444-
typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
445-
446-
template <bool _Dummy>
447-
using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
448-
449-
template <bool _Dummy>
450-
using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
451-
452-
template <bool _Dummy>
453-
using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
454-
455-
template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
456-
using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
457-
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
458-
459-
template <class _ArgType>
460-
using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
461-
462-
template <class _Pp>
463-
using _EnableIfPointerConvertible _LIBCPP_NODEBUG = __enable_if_t< _CheckArrayPointerConversion<_Pp>::value >;
464-
465405
template <class _UPtr, class _Up, class _ElemT = typename _UPtr::element_type>
466406
using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
467407
__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> {
477417
using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
478418

479419
public:
480-
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
420+
template <class _Deleter = deleter_type,
421+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
481422
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
482423

483-
template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
424+
template <class _Deleter = deleter_type,
425+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0>
484426
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
485427

486-
template <class _Pp,
487-
bool _Dummy = true,
488-
class = _EnableIfDeleterDefaultConstructible<_Dummy>,
489-
class = _EnableIfPointerConvertible<_Pp> >
490-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __ptr) _NOEXCEPT
428+
template <class _Ptr,
429+
class _Deleter = deleter_type,
430+
__enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value, int> = 0,
431+
__enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
432+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Ptr __ptr) _NOEXCEPT
491433
: __ptr_(__ptr),
492434
__deleter_() {}
493435

@@ -497,43 +439,38 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI unique_ptr<_Tp[], _Dp> {
497439
: __ptr_(__ptr),
498440
__checker_(__size) {}
499441

500-
template <class _Pp,
501-
bool _Dummy = true,
502-
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
503-
class = _EnableIfPointerConvertible<_Pp> >
504-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __ptr, _LValRefType<_Dummy> __deleter) _NOEXCEPT
442+
template <class _Ptr,
443+
class _Deleter = deleter_type,
444+
__enable_if_t<is_copy_constructible<_Deleter>::value, int> = 0,
445+
__enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
446+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Ptr __ptr, const deleter_type& __deleter) _NOEXCEPT
505447
: __ptr_(__ptr),
506448
__deleter_(__deleter) {}
507449

508-
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
509-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _LValRefType<_Dummy> __deleter) _NOEXCEPT
450+
template <class _Deleter = deleter_type, __enable_if_t<is_copy_constructible<_Deleter>::value, int> = 0>
451+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, const deleter_type& __deleter) _NOEXCEPT
510452
: __ptr_(nullptr),
511453
__deleter_(__deleter) {}
512454

513-
template <class _Pp,
514-
bool _Dummy = true,
515-
class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >,
516-
class = _EnableIfPointerConvertible<_Pp> >
517-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
518-
unique_ptr(_Pp __ptr, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
455+
template <class _Ptr,
456+
class _Deleter = deleter_type,
457+
__enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0,
458+
__enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
459+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Ptr __ptr, deleter_type&& __deleter) _NOEXCEPT
519460
: __ptr_(__ptr),
520-
__deleter_(std::move(__deleter)) {
521-
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
522-
}
461+
__deleter_(std::move(__deleter)) {}
523462

524-
template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
525-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
526-
unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
463+
template <class _Deleter = deleter_type,
464+
__enable_if_t<!is_reference<_Deleter>::value && is_move_constructible<_Deleter>::value, int> = 0>
465+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, deleter_type&& __deleter) _NOEXCEPT
527466
: __ptr_(nullptr),
528-
__deleter_(std::move(__deleter)) {
529-
static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
530-
}
467+
__deleter_(std::move(__deleter)) {}
531468

532-
template <class _Pp,
533-
bool _Dummy = true,
534-
class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >,
535-
class = _EnableIfPointerConvertible<_Pp> >
536-
_LIBCPP_HIDE_FROM_ABI unique_ptr(_Pp __ptr, _BadRValRefType<_Dummy> __deleter) = delete;
469+
template <class _Ptr,
470+
class _Deleter = deleter_type,
471+
__enable_if_t<is_reference<_Deleter>::value, int> = 0,
472+
__enable_if_t<_CheckArrayPointerConversion<_Ptr>::value, int> = 0>
473+
_LIBCPP_HIDE_FROM_ABI unique_ptr(_Ptr, __libcpp_remove_reference_t<deleter_type>&&) = delete;
537474

538475
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
539476
: __ptr_(__u.release()),

0 commit comments

Comments
 (0)