提问人:Fedor 提问时间:8/20/2023 更新时间:8/20/2023 访问量:86
可以为本地类定义友元比较运算符吗?
Can friend comparison operator be defined for a local class?
问:
从 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
只要编译器存在分歧,在上面的两个示例中,哪一个是正确的?
答:
3赞
Jan Schultke
8/20/2023
#1
标准对此非常明确:
当且仅当类是非本地类且函数名称是非限定的时,才能在类的友元声明中定义函数。
您的第一个代码示例是在本地类中定义 a,因此它违反了本段。friend
第二个示例在块范围内定义了一个函数,该函数的格式也明显不正确:
[...]函数只能在命名空间或类范围内定义。[...]
GCC 编译它的事实是一个编译器错误,可能与 GCC 支持本地函数作为编译器扩展这一事实有关。它给出的警告是荒谬的,通常会发生在以下情况下:has 'extern' and is initialized
// <source>:1:12: warning: 'x' initialized and declared 'extern'
// 1 | extern int x = 0;
// | ^
extern int x = 0;
注意:我已经针对此问题提交了错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111079
评论
1赞
Language Lawyer
8/20/2023
GCC 支持将本地函数作为编译器扩展不在 C++ 中
评论
friend
...=default;
...=default;