diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-06-25 21:58:34 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2024-08-23 13:44:11 +0100 |
commit | c429d509a86d61b21298b787948e24a9c97084e3 (patch) | |
tree | b52f2fee673b6de92e3142360edfdd36ff4a963e | |
parent | 952e67c0d131300f263d729a0fe07bc3655dad27 (diff) | |
download | gcc-c429d509a86d61b21298b787948e24a9c97084e3.zip gcc-c429d509a86d61b21298b787948e24a9c97084e3.tar.gz gcc-c429d509a86d61b21298b787948e24a9c97084e3.tar.bz2 |
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.
-rw-r--r-- | libstdc++-v3/include/std/optional | 12 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc | 20 |
2 files changed, 30 insertions, 2 deletions
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 6651686..933a5b1 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<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) 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 0000000..46065f8 --- /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 <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; +} |