Equality means more than just operator==
is valid and returns true. And the standard library concepts require this.
equality_comparable
defines symmetric comparison (equality comparing between the same type). In terms of syntax, this means that t1==t2
has to be a boolean. But there are also semantic requirements that types are expected to provide.
One could define equality between t1
and t2
as follows. If they are equal, then for any (pure) function f
which acts on a T
, f(t1) == f(t2)
.
But for equality between types, this definition is conceptually insufficient. After all, a function f
which takes a T
may not take a U
.
To deal with this fact, C++20 defines equality between T
and U
in terms of a hypothetical third type C
. C
could be T
, U
, or some actual other type. But the main thing C++20 asymmetric equality requires is that there is a type C
(which allows symmetric equality testing) to which references to T
and U
can be implicitly converted. This is the common_reference
type.
This allows the standard to define asymmetric equality in terms of C
. That is, for any function f
which takes a C
, if t == u
, then f(t) == f(u)
.
Consider string
and string_view
. A string
is implicitly convertible to a string_view
. As such, when doing asymmetric comparisons, the comparison conceptually acts as if any string
were converted to a string_view
before doing the comparison. That is, string_view
acts as the type C
.
This provision is here specifically to stop code of the form you're trying to write. Conceptually, your struct A
has no equivalence relationship with string_view
. A function that takes a string_view
couldn't take an A
of equal value at all, even if string_view
were the common reference between them.