Skip to content

Commit

Permalink
Implement LWG-3746 optional's spaceship with U with a type derive…
Browse files Browse the repository at this point in the history
…d from `optional` causes infinite constraint meta-recursion (#3265)
  • Loading branch information
frederick-vs-ja authored Dec 6, 2022
1 parent 66c528a commit 7164d1c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
2 changes: 1 addition & 1 deletion stl/inc/optional
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ _NODISCARD constexpr bool operator>=(const _Ty1& _Left, const optional<_Ty2>& _R
#ifdef __cpp_lib_concepts
// clang-format off
_EXPORT_STD template <class _Ty1, class _Ty2>
requires (!_Is_specialization_v<_Ty2, optional>)
requires (!_Derived_from_specialization_of<_Ty2, optional>)
&& three_way_comparable_with<_Ty1, _Ty2>
_NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2>
operator<=>(const optional<_Ty1>& _Left, const _Ty2& _Right)
Expand Down
21 changes: 12 additions & 9 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,15 @@ using _Algorithm_int_t = conditional_t<is_integral_v<_Ty>, _Ty, ptrdiff_t>;
template <class _Ty>
concept _Destructible_object = is_object_v<_Ty> && destructible<_Ty>;

template <template <class...> class _Template, class... _Args>
void _Derived_from_specialization_impl(const _Template<_Args...>&);

template <class _Ty, template <class...> class _Template>
concept _Derived_from_specialization_of =
requires(const _Ty& _Obj) {
_STD _Derived_from_specialization_impl<_Template>(_Obj); // qualified: avoid ADL, handle incomplete types
};

namespace ranges {
namespace _Iter_move {
#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1681199
Expand Down Expand Up @@ -2932,23 +2941,17 @@ namespace ranges {

_EXPORT_STD struct view_base {};

template <template <class...> class _Template, class... _Args>
void _Derived_from_specialization_impl(const _Template<_Args...>&);

template <class _Ty, template <class...> class _Template>
concept _Derived_from_specialization_of =
is_object_v<_Ty> && requires(const _Ty& _Obj) {
_RANGES _Derived_from_specialization_impl<_Template>(
_Obj); // qualified: avoid ADL, handle incompletable types
};
concept _Strictly_derived_from_specialization_of =
is_object_v<_Ty> && _Derived_from_specialization_of<_Ty, _Template>;

_EXPORT_STD template <class _Derived>
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
class view_interface;

_EXPORT_STD template <class _Ty>
inline constexpr bool enable_view =
derived_from<_Ty, view_base> || _Derived_from_specialization_of<_Ty, view_interface>;
derived_from<_Ty, view_base> || _Strictly_derived_from_specialization_of<_Ty, view_interface>;

_EXPORT_STD template <class _Ty>
concept view = range<_Ty> && movable<_Ty> && enable_view<_Ty>;
Expand Down
10 changes: 10 additions & 0 deletions tests/std/tests/P1614R2_spaceship/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ constexpr bool tuple_like_test() {
return true;
}

template <class T>
struct derived_optional : std::optional<T> {
friend bool operator==(const derived_optional&, const derived_optional&) = default;
};

template <auto SmallVal, decltype(SmallVal) EqualVal, decltype(EqualVal) LargeVal>
constexpr bool optional_test() {
using ReturnType = std::compare_three_way_result_t<decltype(SmallVal)>;
Expand All @@ -310,8 +315,13 @@ constexpr bool optional_test() {
}
{
constexpr std::optional o1(SmallVal);
constexpr derived_optional<decltype(SmallVal)> derived1{std::optional(SmallVal)};
constexpr derived_optional<decltype(SmallVal)> derived2{std::optional(LargeVal)};

static_assert(!std::three_way_comparable<derived_optional<decltype(SmallVal)>>);

assert(spaceship_test<ReturnType>(o1, EqualVal, LargeVal));
assert(spaceship_test<ReturnType>(o1, derived1, derived2));
}
{
constexpr std::optional<decltype(SmallVal)> o1(std::nullopt);
Expand Down

0 comments on commit 7164d1c

Please sign in to comment.