'Adding unrelated operator == renderers spaceship operator(<=>) non-functional
In this code example, it seems that adding unreleated operator== (on a different type) renders the shaceship opreator not functional. This is tested in VS2019. Is it a compiler bug, or some weird behaviour?
class A
{
public:
int x;
};
class B
{
public:
constexpr std::strong_ordering operator<=>(const B& other) const = default;
constexpr bool operator==(const A& other) const { return this->x == other.x; } // remove this so it can compile
int x;
};
class C
{
public:
constexpr operator bool() const { return b1 == b2; }
B b1, b2;
};
The error I get is in the usage of the operator in the class B is:
binary '==': no operator found which takes a left-hand operand of type 'const B' (or there is no acceptable conversion)
Solution 1:[1]
Referring to cppreference's page on how defaulted comparison operators work, let's examine what's happening.
For the first case, with no user-declared operator==:
class B
{
public:
constexpr std::strong_ordering operator<=>(const B& other) const = default;
int x;
};
The following applies:
If
operator<=>is defaulted andoperator==is not declared at all, thenoperator==is implicitly defaulted.
The default signature for operator== is bool operator==(const B& other) const. All well and good.
In your second version, you do declare an operator==. This means you do not get the defaulted operator== as a side-effect of defaulting operator<=>.
class B
{
public:
constexpr std::strong_ordering operator<=>(const B& other) const = default;
constexpr bool operator==(const A& other) const { return this->x == other.x; }
// No additional `operator==` will be generated aside from the above
int x;
};
The problem is that the operator== you declared takes a const A& as the right hand side, instead of a const B&. So you cannot use this operator== to perform a check of the form b1 == b2.
If you want to have both the operator==(const A&) const overload and the default operator==(const B&) const overload, you can explicitly request that the latter be defaulted, like so:
class B
{
public:
constexpr std::strong_ordering operator<=>(const B& other) const = default;
constexpr bool operator==(const B& other) const = default;
// Explicitly request default operator== as well as default operator<=>
constexpr bool operator==(const A& other) const { return this->x == other.x; }
int x;
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Nathan Pierson |
