从 C++20 开始,编译器可以为类生成默认比较运算符,包括作为友元非成员函数,请参阅cppreference.com中的 (2) 。
我遇到了在 MSVC 中工作的代码,它为函数内的本地类执行此操作:
void foo() {
struct A;
bool operator ==(const A&, const A&);
struct A {
friend bool operator ==(const A&, const A&) = default;
};
}
不幸的是,它在 Clang 或 GCC 中不起作用,它们抱怨:
error: cannot define friend function 'operator==' in a local class definition
在线演示: https: //godbolt.org/z/Ts1fer1d1
有一种方法可以让代码被GCC接受:
void foo() {
struct A;
bool operator ==(const A&, const A&);
struct A {
friend bool operator ==(const A&, const A&);
};
bool operator ==(const A&, const A&) = default;
}
现在只打印一些模糊的警告:
warning: declaration of 'bool operator==(const foo()::A&, const foo()::A&)' has 'extern' and is initialized
但另外两个编译器不喜欢,在线演示:https://godbolt.org/z/he1zjj46G
只要编译器存在分歧,上面两个示例中哪一个是正确的?
标准对此说得很清楚:
- [班级.朋友] p6
friend
您的第一个代码示例在本地类中定义 a ,因此它违反了本段。第二个示例在块作用域定义了一个函数,这显然也是格式错误的:
- [dcl.fct.def.general] p2
GCC 编译它的事实是一个编译器错误,可能与 GCC 支持本地函数作为编译器扩展这一事实有关。它给出的警告
has 'extern' and is initialized
是无意义的,通常会发生在以下场景中:注意:我已针对此问题提交了错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi ?id=111079