aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-06-25 21:58:34 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2024-08-23 13:44:11 +0100
commitc429d509a86d61b21298b787948e24a9c97084e3 (patch)
treeb52f2fee673b6de92e3142360edfdd36ff4a963e
parent952e67c0d131300f263d729a0fe07bc3655dad27 (diff)
downloadgcc-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/optional12
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/relops/lwg3746.cc20
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;
+}