c++编译器如何匹配“Class::operator==”?

问题描述 投票:0回答:1

我发现以下代码在c++20之前无法编译:

#include <iostream>
using namespace std;

struct B;
struct C;
struct A {
  A(int v) : val(v) {}
  bool operator==(A &a) { return val == a.val; }

private:
  int val;
  friend struct B;
};
struct B : private A {
  B(int v) : A(v) {};
  bool operator==(A &a) { return this->val == a.val; }
  bool operator==(B &a) { return this->val == a.val; }
};

int main() {
  A a(1);
  B b(2);
  cout << (a == a) << endl;
  cout << (a == b) << endl;
  cout << (b == a) << endl;
  cout << (b == b) << endl;
}

我的 g++ 版本:

g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

用c++17编译

g++ main.cpp -std=c++17
main.cpp: In function ‘int main()’:
main.cpp:24:17: error: ‘A’ is an inaccessible base of ‘B’
   24 |   cout << (a == b) << endl;
      |                 ^

在c++20中编译:

g++ main.cpp -std=c++20
./a.out
1
0
0
1

似乎在c++20之后,如果编译器发现

a == b
无效,它会尝试用
a == b
代替
b == a
。 我的猜测正确吗?

c++ language-lawyer c++20
1个回答
0
投票

似乎在c++20之后,如果编译器发现

a == b
无效,它会尝试用
a == b
代替
b == a
。我的猜测正确吗?

几乎。将合成候选添加到重载候选集中,其中两个参数的顺序相反。这意味着即使

a == b
有效(使用
A::operator==
),它仍然会使用
B::operator==
来执行
b == a
:

[over.match.oper]

对于相等运算符,对于表达式

y == x
的每个非重写候选者,重写候选者还包括一个合成候选者,两个参数的顺序相反。

所以,继承了

public
...

struct B;

struct A {
    A(int v) : val(v) {}
    bool operator==(const A&) const noexcept;

   private:
    int val;
    friend struct B;
};

struct B : public A {     // made public
    B(int v) : A(v) {}

    bool operator==(const A&) const noexcept;
    bool operator==(const B&) const noexcept;
};

...C++17 和 C++20 中将调用不同的重载:

cout << (a == b) << endl; // C++17: A::operator==(const A&)
                          // C++20: B::operator==(const A&)
© www.soinside.com 2019 - 2024. All rights reserved.