https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119714

            Bug ID: 119714
           Summary: Failure when using == operator on a class derived from
                    std::expected
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: makovick at gmail dot com
  Target Milestone: ---

Created attachment 61065
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61065&action=edit
Minimal example

Latest libcxx in GCC 15 master fails to compile when using an equality operator
on a class derived from std::expected.

The convertible_to<bool> requirement at include/c++/expected:1174 seems to be
the culprit.

We actually use custom equality (and spaceship) operators for the derived
class, but this does not seem to make a difference regarding this error.

A simple test case is attached.

GCC 15 output:

/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected: In
substitution of 'template<class _Up>  requires !(__is_expected<_Up>) &&
requires(const _Tp& __t, const _Up& __u) {{__t == __u} -> decltype(auto)
[requires std::convertible_to<<placeholder>, bool>];} constexpr bool
std::operator==(const expected<int, __cxx11::basic_string<char> >&, const _Up&)
[with _Up = int]':
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1175:12:  
required by substitution of 'template<class _Up>  requires
!(__is_expected<_Up>) && requires(const _Tp& __t, const _Up& __u) {{__t == __u}
-> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}
constexpr bool std::operator==(const expected<int, __cxx11::basic_string<char>
>&, const _Up&) [with _Up = int]'
 1175 |             { __t == __u } -> convertible_to<bool>;
      |               ~~~~^~~~~~
test.cc:15:22:   required from here
   15 |   std::cerr << (e == 10) << std::endl;
      |                      ^~
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1178:2:  
required by the constraints of 'template<class _Tp, class _Er> template<class
_Up>  requires !(__is_expected<_Up>) && requires(const _Tp& __t, const _Up&
__u) {{__t == __u} -> decltype(auto) [requires
std::convertible_to<<placeholder>, bool>];} constexpr bool
std::operator==(const expected<_Tp, _Er>&, const _Up&)'
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1174:7:   in
requirements with 'const _Tp& __t', 'const _Up& __u' [with _Tp = int; _Up =
Expected<int, std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >]
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1174:14: error:
satisfaction of atomic constraint 'requires(const _Tp& __t, const _Up& __u)
{{__t == __u} -> decltype(auto) [requires std::convertible_to<<placeholder>,
bool>];} [with _Tp = _Tp; _Up = _Up]' depends on itself
 1174 |           && requires (const _Tp& __t, const _Up& __u) {
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1175 |             { __t == __u } -> convertible_to<bool>;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1176 |           }
      |           ~   
test.cc: In function 'int main()':
test.cc:15:22: warning: C++20 says that these are ambiguous, even though the
second is reversed:
   15 |   std::cerr << (e == 10) << std::endl;
      |                      ^~
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1178:9: note:
candidate 1: 'constexpr bool std::operator==(const expected<_Tp, _Er>&, const
_Up&) [with _Up = int; _Tp = int; _Er = __cxx11::basic_string<char>]'
 1178 |         operator==(const expected& __x, const _Up& __v)
      |         ^~~~~~~~
/usr/lib/gcc/x86_64-conda-linux-gnu/15.0.1/include/c++/expected:1178:9: note:
candidate 2: 'constexpr bool std::operator==(const expected<_Tp, _Er>&, const
_Up&) [with _Up = Expected<int, __cxx11::basic_string<char> >; _Tp = int; _Er =
__cxx11::basic_string<char>]' (reversed)

Reply via email to