我发现以下代码在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++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&)