[gcc r15-9660] libstdc++: Fix constraint recursion in std::expected's operator== [PR119714]

Patrick Palka ppalka@gcc.gnu.org
Mon May 12 14:06:01 GMT 2025


https://gcc.gnu.org/g:0b76b58a5875d519f95a5af661fb64e42a42ed8e

commit r15-9660-g0b76b58a5875d519f95a5af661fb64e42a42ed8e
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon May 12 09:15:34 2025 -0400

    libstdc++: Fix constraint recursion in std::expected's operator== [PR119714]
    
    This std::expected friend operator== is prone to constraint recursion
    after CWG 2369 for the same reason as basic_const_iterator's comparison
    operators were before the r15-7757-g4342c50ca84ae5 workaround.  This
    patch works around the constraint recursion here in a similar manner,
    by making the function parameter of type std::expected dependent in a
    trivial way.
    
            PR libstdc++/119714
            PR libstdc++/112490
    
    libstdc++-v3/ChangeLog:
    
            * include/std/expected (expected::operator==): Replace
            non-dependent std::expected function parameter with a dependent
            one of type expected<_Vp, _Er> where _Vp matches _Tp.
            * testsuite/20_util/expected/119714.cc: New test.
    
    Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    (cherry picked from commit 91bc8169edd9038d78f38bd813287d72e6345c26)

Diff:
---
 libstdc++-v3/include/std/expected                 | 4 ++--
 libstdc++-v3/testsuite/20_util/expected/119714.cc | 9 +++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected
index 5dc1dfbe5b8a..60f1565f15b9 100644
--- a/libstdc++-v3/include/std/expected
+++ b/libstdc++-v3/include/std/expected
@@ -1169,13 +1169,13 @@ namespace __expected
 	    return !__y.has_value() && bool(__x.error() == __y.error());
 	}
 
-      template<typename _Up>
+      template<typename _Up, same_as<_Tp> _Vp>
 	requires (!__expected::__is_expected<_Up>)
 	  && requires (const _Tp& __t, const _Up& __u) {
 	    { __t == __u } -> convertible_to<bool>;
 	  }
 	friend constexpr bool
-	operator==(const expected& __x, const _Up& __v)
+	operator==(const expected<_Vp, _Er>& __x, const _Up& __v)
 	noexcept(noexcept(bool(*__x == __v)))
 	{ return __x.has_value() && bool(*__x == __v); }
 
diff --git a/libstdc++-v3/testsuite/20_util/expected/119714.cc b/libstdc++-v3/testsuite/20_util/expected/119714.cc
new file mode 100644
index 000000000000..a8dc6e891e1d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/expected/119714.cc
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++23 } }
+
+// PR libstdc++/119714 - constraint recursion with std::expected::operator==
+
+#include <expected>
+#include <vector>
+
+using I = std::vector<std::expected<int,int>>::iterator;
+static_assert(std::totally_ordered<I>);


More information about the Libstdc++-cvs mailing list