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)