可以为本地类定义友元比较运算符吗?

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

自 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

只要编译器存在分歧,上面两个示例中哪一个是正确的?

c++ language-lawyer c++20 friend comparison-operators
1个回答
1
投票

标准对此非常明确:

当且仅当该类是非局部类且函数名未限定时,才可以在类的友元声明中定义函数。

- [班级.朋友] p6

您的第一个代码示例在本地类中定义

friend
,因此它违反了本段。

第二个示例在块作用域定义了一个函数,这显然也是格式错误的:

[...] 函数只能在命名空间或类范围内定义。 [...]

- [dcl.fct.def.general] p2

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;
© www.soinside.com 2019 - 2024. All rights reserved.