On Tue, 6 May 2025, Tomasz Kaminski wrote:

> 
> 
> On Mon, May 5, 2025 at 8:50 PM Patrick Palka <ppa...@redhat.com> wrote:
>       Tested on x86_64-pc-linux-gnu, does this look OK for trunk/15?
> 
> This LGTM.
> Out of curiosity, would declaring them as members also fix the issue?

Ah yes it does fix it, and in fact all of expected's operator==
overloads can be converted to member functions.  But IIUC it's generally
preferred in the stdlib to define operator== as non-members, so I guess
we should still go with the below more narrow workaround.  Thanks for
the reviews.

> 
>       -- >8 --
> 
>       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.
>       ---
>        libstdc++-v3/include/std/expected                 | 4 ++--
>        libstdc++-v3/testsuite/20_util/expected/119714.cc | 9 +++++++++
>        2 files changed, 11 insertions(+), 2 deletions(-)
>        create mode 100644 libstdc++-v3/testsuite/20_util/expected/119714.cc
> 
>       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>);
>       --
>       2.49.0.503.g6c0bd1fc70
> 
> 
> 

Reply via email to