如果第二个参数是右值,则重载 != 运算符不起作用

Overloading != operator does not work if second argument is a rvalue

我目前正在尝试了解 C++ 中的运算符重载。我尝试在以下代码中重载运算符“!=”:

#include <iostream>
using namespace std;
class MyClass{
    int a=0;int b=0;
    public:
    MyClass() = default;
    MyClass(int x,int y){a = x;b=y;}
    MyClass(const MyClass& ob){a = ob.a;b = ob.b;}
    MyClass& operator=(const MyClass& ob) = default;
    bool operator!=(const MyClass& ob){
        return a!=ob.a && b!=ob.b;
    }
};
int main() {
    MyClass ob{112,981};
    
    /* This Works
    MyClass ob2{211,121};
    if(ob!=ob2){ */
    
    /*This also works
    if(ob.operator!=({211,121})){ */
    
    //Why does this does not work ??
    if(ob!={211,121}){
        cout<<"Operator != overloaded"<<endl;
    }
    return 0;
}

在主函数中,if(ob!={211,121}){...} 不起作用并导致以下编译错误:

prog.cpp: In function ‘int main()’:
prog.cpp:25:9: error: expected primary-expression before ‘{’ token
  if(ob!={211,121}){
         ^
prog.cpp:25:9: error: expected ‘)’ before ‘{’ token

此外,令我惊讶的是,当我尝试以下变体来实现相同的逻辑时,它起作用了:

 if(ob.operator!=({211,121})){
   return a!=ob.a && b!=ob.b;
 }

有人能解释一下原因吗?

https://godbolt.org/z/9WKf3f97Y

编译器告诉你。例如 GCC 说:

$ g++ -std=c++17 source.cpp && ./a.out
source.cpp: In function ‘int main()’:
source.cpp:24:12: error: expected primary-expression before ‘{’ token
   24 |     if(ob!={211,121}){
      |            ^
source.cpp:24:12: error: expected ‘)’ before ‘{’ token
   24 |     if(ob!={211,121}){
      |       ~    ^
      |            )

而 Clangd(我在 IDE 中使用它)直奔主题:

Initializer list cannot be used on the right hand side of operator '!=' [init_list_bin_op]

所以你根本做不到 something != {init list}。请注意,在更简单的情况下也是如此:

int x = {}; // ok
x != {};    // not ok

请注意,这与 != 的右值是右值无关。事实上 ob != MyClass{211,121} 有效,并且 MyClass{211,121} 是一个右值。

至于为什么 ob.operator!=({211,121}) 可以正常工作,是因为它是对 operator!= 成员函数的函数调用,已知该成员函数采用 const MyClass&,而 {211,121} 可以转换为.

关于为什么 {init-list}禁止在运算符之后,已经解释清楚了here.