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)