Friend 成员函数可以在 GCC 中编译,但不能在 Clang 或 MSVC 中编译

Bak*_*aki 6 c++ templates friend-function language-lawyer

我一直在使用以下使用 GCC 编译的程序,但被 Clang 和 MSVC 拒绝。

Godbolt 演示链接

template <typename>
class X {
   
    void f(){}
};
class Y
{
    friend void X<int>::f();  
};

int main()
{
    X<int> t;
    t.f();
    Y b;
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,上面的程序适用于 GCC,但 Clang 说:

<source>:9:25: error: friend function 'f' is a private member of 'X<int>'
    friend void X<int>::f();  
                ~~~~~~~~^
<source>:9:25: note: implicitly declared private here
<source>:15:7: error: 'f' is a private member of 'X<int>'
    t.f();
      ^
<source>:9:25: note: implicitly declared private here
    friend void X<int>::f();  
                        ^
2 errors generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

我想知道程序的正确行为是什么;根据标准,哪个编译器是正确的?我正在使用 C++20。

use*_*570 4

该程序格式不正确,因为在包含友元声明的X<int>::f类中无法访问限定名称。这可以从class.friendY中看到:

由友元声明指定的名称应在包含友元声明的类范围内可访问。 无论友元声明出现在类成员规范的私有、受保护或公共 ([class.mem]) 部分中,友元声明的含义都是相同的。

(强调我的)

X<int>::f并且由于友元声明指定的名称friend void X<int>::f();在包含类中不可访问Y,因此该程序格式不正确,并且GCC 在接受该程序时是错误的


这是相应的 GCC bug:

GCC 接受成员函数的无效且不可访问的友元声明