5 c++ namespaces inline language-lawyer
引用了N3797的7.3.1/8:
内联命名空间的成员可以在大多数方面使用,就像它们是封闭命名空间的成员一样.
请考虑以下代码段:
namespace M
{
int j = 7;
inline namespace MM
{
int j = 8;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这个例子违反了ODR.但事实并非如此,它正在编制成功.你能解释一下这种行为吗?
7.3p1命名空间[basic.namespace]命名空间是一个可选命名的声明性区域。命名空间的名称可用于访问在该命名空间中声明的实体;即命名空间的成员。与其他声明性区域不同,名称空间的定义可以分为一个或多个翻译单元的多个部分。
命名空间内声明的实体属于该命名空间,即。它是该特定命名空间的成员,无论该命名空间是否内联。
您的示例代码片段不违反ODR ,主要是因为您有 2 个不同的实体名为j;
namespace N {
int j = 0; // 1st
inline namespace M {
int j = 1; // 2nd
}
}
Run Code Online (Sandbox Code Playgroud)
正如 中进一步指出的[namespace.def]p8,封闭命名空间中的名称查找将包括在任何inline命名空间中找到的名称,但嵌套内联命名空间的成员仍然是它们自己的实体。
7.3.1p8命名空间定义[namespace.def]具体来说,内联命名空间及其封闭命名空间都被添加到参数相关的 lokoup (3.4.2) 中使用的一组关联命名空间中,只要其中一个是,以及命名内联命名空间的使用方向 (7.3.4)与未命名的命名空间 (7.3.1.1) 一样,隐式插入到封闭的命名空间中。
此外,内联命名空间的每个成员随后都可以显式实例化(14.7.2)或显式专门化(14.7.3),就好像它是封闭命名空间的成员一样。最后,通过显式限定(3.4.3.2)在封闭命名空间中查找名称将包括由 using 指令引入的内联命名空间的成员,即使封闭命名空间中存在该名称的声明。
添加的名称不会被视为先前声明的实体的重新声明,它们是嵌套声明区域中的附加名称,在名称查找期间被带入封闭的命名空间。
注意:依靠编译器发出 ODR 违规诊断并不安全,主要是因为标准明确规定,如果应用程序违反了所设置的规则,则“不需要诊断”。
[basic.def.odr].
更多详细信息可在Matthieu M.对这篇文章的评论。
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |