mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-26 21:33:59 +08:00
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.
This commit is contained in:
parent
952e67c0d1
commit
c429d509a8
@ -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<T>)
|
||||
#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<typename _Tp>
|
||||
concept __is_derived_from_optional = requires (const _Tp& __t) {
|
||||
[]<typename _Up>(const optional<_Up>&){ }(__t);
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
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)
|
||||
|
20
libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc
Normal file
20
libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc
Normal file
@ -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 <optional>
|
||||
|
||||
struct S : std::optional<char>
|
||||
{
|
||||
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<char>& o)
|
||||
{
|
||||
return s <=> o;
|
||||
}
|
Loading…
Reference in New Issue
Block a user