Skip to content

[libc++][NFC] Make enable_ifs in <optional> consistent #127184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 15, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 114 additions & 121 deletions libcxx/include/optional
Original file line number Diff line number Diff line change
Expand Up @@ -672,44 +672,41 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr optional(optional&&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr optional(nullopt_t) noexcept {}

template <
class _InPlaceT,
class... _Args,
class = enable_if_t< _And< _IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...> >::value > >
template <class _InPlaceT,
class... _Args,
enable_if_t<_And<_IsSame<_InPlaceT, in_place_t>, is_constructible<value_type, _Args...>>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_InPlaceT, _Args&&... __args)
: __base(in_place, std::forward<_Args>(__args)...) {}

template <class _Up,
class... _Args,
class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> >
enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
: __base(in_place, __il, std::forward<_Args>(__args)...) {}

template <class _Up = value_type,
enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
template <class _Up = value_type,
enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}

template <class _Up, enable_if_t< _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}

// LWG2756: conditionally explicit conversion from const optional<_Up>&
template <class _Up,
enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
this->__construct_from(__v);
}
template <class _Up,
enable_if_t< _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
this->__construct_from(__v);
}

// LWG2756: conditionally explicit conversion from optional<_Up>&&
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
this->__construct_from(std::move(__v));
}
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
this->__construct_from(std::move(__v));
}
Expand All @@ -718,7 +715,7 @@ public:
template <class _Tag,
class _Fp,
class... _Args,
__enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
enable_if_t<_IsSame<_Tag, __optional_construct_from_invoke_tag>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Tag, _Fp&& __f, _Args&&... __args)
: __base(__optional_construct_from_invoke_tag{}, std::forward<_Fp>(__f), std::forward<_Args>(__args)...) {}
# endif
Expand All @@ -732,12 +729,12 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default;

// LWG2756
template <
class _Up = value_type,
class = enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Up>, optional>,
_Or< _IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>> >,
is_constructible<value_type, _Up>,
is_assignable<value_type&, _Up> >::value> >
template <class _Up = value_type,
enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
_Or<_IsNotSame<__remove_cvref_t<_Up>, value_type>, _Not<is_scalar<value_type>>>,
is_constructible<value_type, _Up>,
is_assignable<value_type&, _Up>>::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
if (this->has_value())
this->__get() = std::forward<_Up>(__v);
Expand All @@ -747,21 +744,20 @@ public:
}

// LWG2756
template <class _Up,
enable_if_t< _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(const optional<_Up>& __v) {
this->__assign_from(__v);
return *this;
}

// LWG2756
template <class _Up, enable_if_t< _CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_assign<_Up>(), int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(optional<_Up>&& __v) {
this->__assign_from(std::move(__v));
return *this;
}

template <class... _Args, class = enable_if_t< is_constructible_v<value_type, _Args...> > >
template <class... _Args, enable_if_t<is_constructible_v<value_type, _Args...>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
reset();
this->__construct(std::forward<_Args>(__args)...);
Expand All @@ -770,7 +766,7 @@ public:

template <class _Up,
class... _Args,
class = enable_if_t< is_constructible_v<value_type, initializer_list<_Up>&, _Args...> > >
enable_if_t<is_constructible_v<value_type, initializer_list<_Up>&, _Args...>, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
reset();
this->__construct(__il, std::forward<_Args>(__args)...);
Expand Down Expand Up @@ -982,77 +978,75 @@ public:
using __base::reset;
};

# if _LIBCPP_STD_VER >= 17
template <class _Tp>
optional(_Tp) -> optional<_Tp>;
# endif

// Comparisons between optionals
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x == *__y;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
return false;
return *__x != *__y;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__y))
return false;
if (!static_cast<bool>(__x))
return true;
return *__x < *__y;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__x))
return false;
if (!static_cast<bool>(__y))
return true;
return *__x > *__y;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__x))
return true;
if (!static_cast<bool>(__y))
return false;
return *__x <= *__y;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) {
if (!static_cast<bool>(__y))
return true;
if (!static_cast<bool>(__x))
Expand Down Expand Up @@ -1145,99 +1139,99 @@ _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>&
# endif // _LIBCPP_STD_VER <= 17

// Comparisons with T
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x == __v : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>,
bool >
operator==(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v == *__x : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x != __v : true;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>,
bool >
operator!=(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v != *__x : true;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x < __v : true;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>,
bool >
operator<(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v < *__x : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x <= __v : true;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>,
bool >
operator<=(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v <= *__x : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x > __v : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>,
bool >
operator>(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v > *__x : true;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const optional<_Tp>& __x, const _Up& __v) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const optional<_Tp>& __x, const _Up& __v) {
return static_cast<bool>(__x) ? *__x >= __v : false;
}

template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<
is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>,
bool >
operator>=(const _Tp& __v, const optional<_Up>& __x) {
template <
class _Tp,
class _Up,
enable_if_t<is_convertible_v<decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()), bool>, int> = 0>
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __v, const optional<_Up>& __x) {
return static_cast<bool>(__x) ? __v >= *__x : true;
}

Expand All @@ -1252,9 +1246,8 @@ operator<=>(const optional<_Tp>& __x, const _Up& __v) {

# endif // _LIBCPP_STD_VER >= 20

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX20 enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, void >
template <class _Tp, enable_if_t< is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) {
__x.swap(__y);
}
Expand Down