我读了关于命名空间定义的部分。N3797的7.3.1条说。
inline关键字只有在扩展命名空间定义中使用过,才可以在该命名空间的原始命名空间定义中使用。
请看下面的代码片段。
namespace M
{
int h;
}
inline namespace M
{
int j = 6;
}
这段代码在编译成功后 -std=c++11
而没有这个选项。你能解释这种行为吗?它是一个 g++
bug?
我们对标准的引用是明确的:这是不允许的。
使用 Clang++,我得到了非常清晰的错误信息。
Test0614-1.cpp:17:18: error: non-inline namespace cannot be reopened as inline
inline namespace M
^
Test0614-1.cpp:12:11: note: previous definition is here
namespace M
^
所以这绝对是g++中的一个错误. 顺便说一下,它在这里被报告了。https:/gcc.gnu.orgbugzillashow_bug.cgi?id=53402。
编译器接受以前版本的标准的内联命名空间,而且没有至少一个警告,这似乎是一个问题。 这个问题在2010年已经被报告为bug,应该已经被修正了。 https:/gcc.gnu.orgbugzillashow_bug.cgi?id=43824。
namespace M
{
int h;
}
inline namespace M
{
int j = 6;
}
这将导致 "非内联命名空间不能作为内联命名空间打开 "的错误。
你必须使用。
inline namespace M
{
int h;
}
inline namespace M
{
int j = 6;
}
反过来说,你应该得到一个警告,说你把一个内联命名空间重新打开成一个非内联命名空间。
inline namespace M
{
int h;
}
namespace M
{
int j = 6;
}
但从我的观察来看,它根本没有改变任何东西,所以我不知道为什么警告会存在,但事实上它的存在和 ::inline
则表明不是这样。
namespace M
{
inline namespace F {
int h;
}
}
namespace M::F {
int k;
}
给出了同样的警告,当使用时,会被抑制。
namespace M::inline F {
int k;
}
有趣的是,这是非法的。
inline namespace M
{
inline namespace F {
int h;
}
}
inline namespace M::inline F {
int k;
}
你可以使用 namespace M::inline F
或 namespace M::F
但在这两种情况下,你都会得到一个警告,说你把内联命名空间 M 开启为一个非内联命名空间。
这可能只是因为 ::inline
的存在只是为了抑制这种警告,让程序员从扩展命名空间中意识到这是一个内联命名空间,可以在没有作用域解析操作符的情况下进行访问,而不需要他们检查主命名空间的定义,这样就可以明确代码和意图,而且由于大多数内联命名空间用于版本管理,在全局命名空间作用域下,它们总是嵌套在一个非内联命名空间内,因此,其语法 inline namespace M::inline F
是不需要被允许的。以前 namespace M {inline F {int k;}}
不得不使用 namespace M::F
以便在扩展名空间块上明确这一意图。