https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119714
Erik Bråthen Solem <erikbsolem at hotmail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |erikbsolem at hotmail dot com
--- Comment #5 from Erik Bråthen Solem <erikbsolem at hotmail dot com> ---
So the problematic equality operator is:
template< class T2 >
friend constexpr bool operator==( const expected& lhs, const T2& val );
In GCC 15’s <expected> header the definition looks like this after the
constraints were added:
template<typename _Up>
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)
noexcept(noexcept(bool(*__x == __v)))
{ return __x.has_value() && bool(*__x == __v); }
According to cppreference this operator requires that *lhs == val is
well-formed, with the exact wording being changed between C++23 and C++26.
Perhaps a dumb question, but should it not be
{ *__t == __u } -> convertible_to<bool>;
then, instead of
{ __t == __u } -> convertible_to<bool>;
i.e., with the asterisk? Since it is the contained value of lhs (not the
container) that must be comparable to val?
I tried the following comparisons:
expected<int, int> e = 42;
function<expected<int, int>()> fun;
fun == nullptr;
*e == fun;
- GCC 14.2 accepts both comparisons (but the program SEGFAULTs upon execution
because *e == fun does not make sense).
- GCC 15.1 reports this circular dependency for both.
- GCC 15.1 where I manually edited expected as suggested above accepts the
first one and rejects the second one, this time with the correct “no match for
'operator=='” message, and the printout shows that the candidate operator in
question is skipped with reason “constraints not satisfied” (and not because
something depends on itself).