当封闭命名空间内联时的嵌套命名空间定义
Nested namespace definition when the enclosing namespace is inline
考虑以下演示程序
#include <iostream>
inline namespace A
{
}
namespace A:: inline B
{
void f() { std::cout << "Hello nested namespace definition.\n"; }
}
int main()
{
f();
return 0;
}
程序经过编译器clang HEAD 11.0.0
编译后的结果如下
prog.cc:7:11: warning: inline namespace reopened as a non-inline namespace
namespace A:: inline B
^
inline
prog.cc:3:18: note: previous definition is here
inline namespace A
^
1 warning generated.
Hello nested namespace definition.
但根据嵌套命名空间定义的语法,我可能不会在命名空间 A 之前使用关键字 inline
。
这是编译器的错误还是我做错了什么?
顺便说一下,编译器 gcc HEAD 10.0.1 20200
编译程序时没有任何警告。
clang 的 fixit-hint 具有误导性(因为你实际上不能做它告诉你做的事情),但程序很好(尽管具有误导性,因为它看起来像你在声明一个非内联命名空间当你真的不是 - 所以警告并非完全不合理)。
暂时忽略嵌套命名空间,这其实没问题:
inline namespace N { int i=0; };
namespace N { int j=1; };
int k=j;
我们拥有的唯一规则,来自 [namespace.def]/3,是(强调我的):
The inline
keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definition that initially declared the namespace-name for that namespace.
措辞是 "only if",而不是 "if and only if" - 因此您不能标记以前未标记的名称空间 inline
...但是如果名称空间的第一个声明是 inline
,并非每个后续声明都必须是。
如 OP 中所述,clang 无论如何都会对此发出警告。因为有点误导。
但为什么我们不能在其中插入前导 inline
?
如 the paper 中所述,允许嵌套命名空间与 前导 命名空间 inline
的问题在于它会导致程序员产生歧义:
inline namespace std::experimental::parallelism_v2; // not immediately to reader,
// is std or parallelism_v2 inline?
如果您通过将前导 inline
与嵌套 inline
放在 namespace
的另一侧来协调前导 inline
,情况也是如此:
namespace inline std::experimental::parallelism_v2; // immediately to reader?
// std or parallelism_v2 inline?
所以这意味着不支持。如果你想要一个带有顶级命名空间 inline
的嵌套命名空间......你不能。顶级命名空间必须是非 inline
(我想我们可以考虑像 namespace ::inline N::inline M
这样的语法,但它以其自身的方式很奇怪)。
考虑以下演示程序
#include <iostream>
inline namespace A
{
}
namespace A:: inline B
{
void f() { std::cout << "Hello nested namespace definition.\n"; }
}
int main()
{
f();
return 0;
}
程序经过编译器clang HEAD 11.0.0
编译后的结果如下
prog.cc:7:11: warning: inline namespace reopened as a non-inline namespace
namespace A:: inline B
^
inline
prog.cc:3:18: note: previous definition is here
inline namespace A
^
1 warning generated.
Hello nested namespace definition.
但根据嵌套命名空间定义的语法,我可能不会在命名空间 A 之前使用关键字 inline
。
这是编译器的错误还是我做错了什么?
顺便说一下,编译器 gcc HEAD 10.0.1 20200
编译程序时没有任何警告。
clang 的 fixit-hint 具有误导性(因为你实际上不能做它告诉你做的事情),但程序很好(尽管具有误导性,因为它看起来像你在声明一个非内联命名空间当你真的不是 - 所以警告并非完全不合理)。
暂时忽略嵌套命名空间,这其实没问题:
inline namespace N { int i=0; };
namespace N { int j=1; };
int k=j;
我们拥有的唯一规则,来自 [namespace.def]/3,是(强调我的):
The
inline
keyword may be used on a namespace-definition that extends a namespace only if it was previously used on the namespace-definition that initially declared the namespace-name for that namespace.
措辞是 "only if",而不是 "if and only if" - 因此您不能标记以前未标记的名称空间 inline
...但是如果名称空间的第一个声明是 inline
,并非每个后续声明都必须是。
如 OP 中所述,clang 无论如何都会对此发出警告。因为有点误导。
但为什么我们不能在其中插入前导 inline
?
如 the paper 中所述,允许嵌套命名空间与 前导 命名空间 inline
的问题在于它会导致程序员产生歧义:
inline namespace std::experimental::parallelism_v2; // not immediately to reader,
// is std or parallelism_v2 inline?
如果您通过将前导 inline
与嵌套 inline
放在 namespace
的另一侧来协调前导 inline
,情况也是如此:
namespace inline std::experimental::parallelism_v2; // immediately to reader?
// std or parallelism_v2 inline?
所以这意味着不支持。如果你想要一个带有顶级命名空间 inline
的嵌套命名空间......你不能。顶级命名空间必须是非 inline
(我想我们可以考虑像 namespace ::inline N::inline M
这样的语法,但它以其自身的方式很奇怪)。