当封闭命名空间内联时的嵌套命名空间定义

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 这样的语法,但它以其自身的方式很奇怪)。