Skip to content

Commit 7239fa1

Browse files
committed
[libc++] Refactor optional constructors to use conditional explicit
1 parent 3b10b9a commit 7239fa1

File tree

2 files changed

+44
-101
lines changed

2 files changed

+44
-101
lines changed

libcxx/include/__tuple/sfinae_helpers.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,6 @@
1717

1818
_LIBCPP_BEGIN_NAMESPACE_STD
1919

20-
#ifndef _LIBCPP_CXX03_LANG
21-
22-
struct _LIBCPP_EXPORTED_FROM_ABI __check_tuple_constructor_fail {
23-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit_default() { return false; }
24-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { return false; }
25-
template <class...>
26-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit() {
27-
return false;
28-
}
29-
template <class...>
30-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit() {
31-
return false;
32-
}
33-
template <class...>
34-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_assign() {
35-
return false;
36-
}
37-
};
38-
#endif // !defined(_LIBCPP_CXX03_LANG)
39-
4020
#if _LIBCPP_STD_VER >= 17
4121

4222
template <bool _CanCopy, bool _CanMove>

libcxx/include/optional

Lines changed: 44 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -604,69 +604,20 @@ private:
604604
static_assert(!is_array_v<value_type>, "instantiation of optional with an array type is ill-formed");
605605

606606
// LWG2756: conditionally explicit conversion from _Up
607-
struct _CheckOptionalArgsConstructor {
608-
template <class _Up>
609-
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
610-
return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>;
611-
}
612607

613-
template <class _Up>
614-
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
615-
return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>;
616-
}
617-
};
618-
template <class _Up>
619-
using _CheckOptionalArgsCtor _LIBCPP_NODEBUG =
620-
_If< _IsNotSame<__remove_cvref_t<_Up>, in_place_t>::value && _IsNotSame<__remove_cvref_t<_Up>, optional>::value &&
621-
(!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value),
622-
_CheckOptionalArgsConstructor,
623-
__check_tuple_constructor_fail >;
624-
template <class _QualUp>
625-
struct _CheckOptionalLikeConstructor {
626-
template <class _Up, class _Opt = optional<_Up>>
627-
using __check_constructible_from_opt _LIBCPP_NODEBUG =
628-
_Or< is_constructible<_Tp, _Opt&>,
629-
is_constructible<_Tp, _Opt const&>,
630-
is_constructible<_Tp, _Opt&&>,
631-
is_constructible<_Tp, _Opt const&&>,
632-
is_convertible<_Opt&, _Tp>,
633-
is_convertible<_Opt const&, _Tp>,
634-
is_convertible<_Opt&&, _Tp>,
635-
is_convertible<_Opt const&&, _Tp> >;
636-
template <class _Up, class _Opt = optional<_Up>>
637-
using __check_assignable_from_opt _LIBCPP_NODEBUG =
638-
_Or< is_assignable<_Tp&, _Opt&>,
639-
is_assignable<_Tp&, _Opt const&>,
640-
is_assignable<_Tp&, _Opt&&>,
641-
is_assignable<_Tp&, _Opt const&&> >;
642-
template <class _Up, class _QUp = _QualUp>
643-
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() {
644-
return is_convertible<_QUp, _Tp>::value &&
645-
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
646-
}
647-
template <class _Up, class _QUp = _QualUp>
648-
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() {
649-
return !is_convertible<_QUp, _Tp>::value &&
650-
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_Up>::value);
651-
}
652-
template <class _Up, class _QUp = _QualUp>
653-
_LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() {
654-
// Construction and assignability of _QUp to _Tp has already been
655-
// checked.
656-
return !__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value;
657-
}
658-
};
608+
template <class _Up, class _Opt = optional<_Up>>
609+
using __check_constructible_from_opt _LIBCPP_NODEBUG =
610+
_Or<is_constructible<_Tp, _Opt&>,
611+
is_constructible<_Tp, _Opt const&>,
612+
is_constructible<_Tp, _Opt&&>,
613+
is_constructible<_Tp, _Opt const&&>>;
659614

660-
template <class _Up, class _QualUp>
661-
using _CheckOptionalLikeCtor _LIBCPP_NODEBUG =
662-
_If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp> >::value,
663-
_CheckOptionalLikeConstructor<_QualUp>,
664-
__check_tuple_constructor_fail >;
665-
template <class _Up, class _QualUp>
666-
using _CheckOptionalLikeAssign _LIBCPP_NODEBUG =
667-
_If< _And< _IsNotSame<_Up, _Tp>, is_constructible<_Tp, _QualUp>, is_assignable<_Tp&, _QualUp> >::value,
668-
_CheckOptionalLikeConstructor<_QualUp>,
669-
__check_tuple_constructor_fail >;
615+
template <class _Up, class _Opt = optional<_Up>>
616+
using __check_assignable_from_opt _LIBCPP_NODEBUG =
617+
_Or<is_assignable<_Tp&, _Opt&>,
618+
is_assignable<_Tp&, _Opt const&>,
619+
is_assignable<_Tp&, _Opt&&>,
620+
is_assignable<_Tp&, _Opt const&&>>;
670621

671622
public:
672623
_LIBCPP_HIDE_FROM_ABI constexpr optional() noexcept {}
@@ -686,30 +637,34 @@ public:
686637
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
687638
: __base(in_place, __il, std::forward<_Args>(__args)...) {}
688639

689-
template <class _Up = value_type,
690-
enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
691-
_LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
692-
693-
template <class _Up, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
694-
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
640+
template <class _Up,
641+
class _DependentU = enable_if_t<
642+
!is_same_v<__remove_cvref_t<_Up>, in_place_t> && !is_same_v<__remove_cvref_t<_Up>, optional> &&
643+
(!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_optional<__remove_cvref_t<_Up>>::value),
644+
_Up>,
645+
enable_if_t<is_constructible_v<_Tp, _DependentU>, int> = 0>
646+
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&&, _Tp>) optional(_Up&& __v)
647+
: __base(in_place, std::forward<_Up>(__v)) {}
695648

696649
// LWG2756: conditionally explicit conversion from const optional<_Up>&
697-
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
698-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
699-
this->__construct_from(__v);
700-
}
701-
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
702-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
650+
template <class _Up,
651+
class _DependentU = enable_if_t<!is_same_v<_Up, _Tp>, _Up>,
652+
enable_if_t<is_constructible_v<_Tp, const _DependentU&> &&
653+
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_DependentU>::value),
654+
int> = 0>
655+
_LIBCPP_HIDE_FROM_ABI
656+
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<const _Up&, _Tp>) optional(const optional<_Up>& __v) {
703657
this->__construct_from(__v);
704658
}
705659

706660
// LWG2756: conditionally explicit conversion from optional<_Up>&&
707-
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
708-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
709-
this->__construct_from(std::move(__v));
710-
}
711-
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
712-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
661+
template <class _Up,
662+
class _DependentU = enable_if_t<!is_same_v<_Up, _Tp>, _Up>,
663+
enable_if_t<is_constructible_v<_Tp, _DependentU&&> &&
664+
(is_same_v<remove_cv_t<_Tp>, bool> || !__check_constructible_from_opt<_DependentU>::value),
665+
int> = 0>
666+
_LIBCPP_HIDE_FROM_ABI
667+
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<_Up&&, _Tp>) optional(optional<_Up>&& __v) {
713668
this->__construct_from(std::move(__v));
714669
}
715670

@@ -746,14 +701,22 @@ public:
746701
}
747702

748703
// LWG2756
749-
template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
704+
template <class _Up,
705+
class _DependentU = enable_if_t<!is_same_v<_Tp, _Up>, _Up>,
706+
enable_if_t<is_constructible_v<_Tp, const _DependentU&> && is_assignable_v<_Tp&, const _DependentU&> &&
707+
!__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value,
708+
int> = 0>
750709
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
751710
this->__assign_from(__v);
752711
return *this;
753712
}
754713

755714
// LWG2756
756-
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
715+
template <class _Up,
716+
class _DependentU = enable_if_t<!is_same_v<_Tp, _Up>, _Up>,
717+
enable_if_t<is_constructible_v<_Tp, _DependentU&&> && is_assignable_v<_Tp&, _DependentU&&> &&
718+
!__check_constructible_from_opt<_Up>::value && !__check_assignable_from_opt<_Up>::value,
719+
int> = 0>
757720
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
758721
this->__assign_from(std::move(__v));
759722
return *this;

0 commit comments

Comments
 (0)