From: Jonathan Wakely Date: Tue, 25 Jun 2024 20:58:34 +0000 (+0100) Subject: libstdc++: Implement LWG 3746 for std::optional X-Git-Tag: basepoints/gcc-16~6419 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c429d509a86d61b21298b787948e24a9c97084e3;p=thirdparty%2Fgcc.git libstdc++: Implement LWG 3746 for std::optional This avoids constraint recursion in operator<=> for std::optional. The resolution was approved in Kona 2022. libstdc++-v3/ChangeLog: * include/std/optional (__is_derived_from_optional): New concept. (operator<=>): Use __is_derived_from_optional. * testsuite/20_util/optional/relops/lwg3746.cc: New test. --- diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 6651686cd1d..933a5b15e56 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -1581,9 +1581,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !__rhs; } #endif // three-way-comparison +#if __cpp_lib_concepts // _GLIBCXX_RESOLVE_LIB_DEFECTS // 4072. std::optional comparisons: constrain harder -#if __cpp_lib_concepts # define _REQUIRES_NOT_OPTIONAL(T) requires (!__is_optional_v) #else # define _REQUIRES_NOT_OPTIONAL(T) @@ -1675,8 +1675,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !__rhs || __lhs >= *__rhs; } #ifdef __cpp_lib_three_way_comparison + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3746. optional's spaceship with U with a type derived from optional + // causes infinite constraint meta-recursion + template + concept __is_derived_from_optional = requires (const _Tp& __t) { + [](const optional<_Up>&){ }(__t); + }; + template - requires (!__is_optional_v<_Up>) + requires (!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Up, _Tp> constexpr compare_three_way_result_t<_Tp, _Up> operator<=> [[nodiscard]] (const optional<_Tp>& __x, const _Up& __v) diff --git a/libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc b/libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc new file mode 100644 index 00000000000..46065f8e901 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc @@ -0,0 +1,20 @@ +// { dg-do compile { target c++20 } } + +// LWG 3746. optional's spaceship with U with a type derived from optional +// causes infinite constraint meta-recursion + +#include + +struct S : std::optional +{ + bool operator==(const S&) const; + bool operator<(const S&) const; + bool operator>(const S&) const; + bool operator<=(const S&) const; + bool operator>=(const S&) const; +}; + +auto cmp(const S& s, const std::optional& o) +{ + return s <=> o; +}