简体   繁体   中英

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)

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 and operator== is not declared at all, then operator== 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;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM