首页 > 解决方案 > 封闭命名空间内联时的嵌套命名空间定义

问题描述

考虑以下演示程序

#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.

但是根据嵌套命名空间定义的语法,我可能不会inline在命名空间 A 之前使用关键字。

那么这是编译器的错误还是我做错了什么?

顺便说一句,编译器gcc HEAD 10.0.1 20200在没有任何警告的情况下编译程序。

标签: c++namespacesdefinitionc++20inline-namespaces

解决方案


clang 的 fixit-hint 具有误导性(因为您实际上无法执行它告诉您做的事情),但程序很好(尽管具有误导性,因为看起来您在声明非内联命名空间时)真的不是 - 所以警告并非完全不合理)。


暂时忽略嵌套的命名空间,这实际上很好:

inline namespace N { int i=0; };
namespace N { int j=1; };
int k=j;

我们唯一的规则,来自[namespace.def]/3,是(强调我的):

当关键字先前用于最初声明该名称空间的名称空间名称的名称空间定义时,该inline关键字才可用于扩展名称空间的名称空间定义

措辞是“仅当”,而不是“当且仅当”-因此您不能标记inline以前未标记的命名空间......但如果命名空间的第一个声明是inline,则并非每个后续声明都必须是。

正如 OP 中所指出的,无论如何,clang 都会对此发出警告。因为这有点误导。


但是为什么我们不能inline在里面放一个领先呢?

论文中所述,允许嵌套命名空间与前导命名空间的问题inline在于它会导致程序员产生歧义:

inline namespace std::experimental::parallelism_v2;  // not immediately to reader,
                                                     // is std or parallelism_v2 inline?

如果您通过将其放在 的另一侧来协调前导inline与嵌套,情况也是如此:inlinenamespace

namespace inline std::experimental::parallelism_v2;  // immediately to reader?
                                                     // std or parallelism_v2 inline?

所以暗示不支持。如果你想要一个具有顶级命名空间的嵌套命名空间inline......你不能。顶级命名空间必须是非 - inline(我想我们可以考虑类似的语​​法namespace ::inline N::inline M,但这只是以它自己的方式很奇怪)。



推荐阅读