【发布时间】:2020-04-10 11:35:03
【问题描述】:
考虑以下程序
#include <iostream>
namespace N1
{
inline namespace N2
{
class A
{
public:
friend void f( const A & );
private:
int x = 10;
};
//void f( const A & );
}
void N2::f( const A &a ) { std::cout << a.x << '\n'; }
}
int main()
{
using namespace N1;
A a;
f( a );
}
根据 C++ 17 标准(10.3.1.2 命名空间成员定义)
3 如果非本地类中的友元声明首先声明了一个类, 函数、类模板或函数模板97 朋友是成员 最里面的封闭命名空间。朋友声明不 本身使名称对非限定查找(6.4.1)可见或 合格的查找 (6.4.3)。
所以友元函数的名称在命名空间 N2 中是不可见的。所以它在命名空间 N1 中也应该是不可见的。
但是,clang HEAD 10.0.0 编译和执行代码时不会发出警告。
编译器gcc HEAD 10.0.0 20191发出警告
prog.cc:18:10: warning: 'void N1::N2::f(const N1::N2::A&)' has not been declared within 'N1::N2'
18 | void N2::f( const A &a ) { std::cout << a.x << '\n'; }
| ^~
prog.cc:10:25: note: only here as a 'friend'
10 | friend void f( const A & );
| ^
但是运行程序并输出正确的结果。
Visual C++ 2019 也成功编译了代码,没有警告,程序输出了预期的结果。
是否存在三个编译器的错误,因为名称 f 是不可见的,所以封闭命名空间中友元函数 f 的定义不正确?
【问题讨论】:
-
它是如何隐形的?你清楚地定义了它,所以它是可见的。
-
@ÖöTiib 请参阅 C++ 标准的引用。
-
哪里说函数的定义不可见了?
-
尽管 N2::f 已在发布的代码中明确定义?
-
@ÖöTiib 还有一个。名称 f 在命名空间 N2 中是不可见的。那么如果限定名查找找不到函数,如何在封闭的命名空间 N1 中定义函数呢?
标签: c++ namespaces language-lawyer c++17 friend-function