将名称空间的成员重新定义为嵌套的内联名称空间
Redefinition member of the namespace into the nested inline namespace
有一个N3797的7.3.1/8的报价:
考虑下面的代码片段:内联命名空间的成员在大多数情况下都可以像这样使用它们是封闭命名空间的成员。
namespace M
{
int j = 7;
inline namespace MM
{
int j = 8;
}
}
我认为这个例子违反了ODR
。但事实并非如此,它正在成功编译。你能解释这种行为吗?
简介
7.3p1
Namespaces[basic.namespace]
命名空间是一个可选命名的声明性区域。命名空间的名称可以用来访问在该命名空间中声明的实体;即名称空间的成员。与其他声明性区域不同,名称空间的定义可以拆分为一个或多个翻译单元的几个部分。
名称空间中的声明实体属于该名称空间。它是该特定名称空间的成员,无论该名称空间是否为inline。
ODR VIOLATION = no0ne
你的例子片段没有违反ODR,主要是因为你有两个不同的实体命名为j
;
namespace N {
int j = 0; // 1st
inline namespace M {
int j = 1; // 2nd
}
}
正如[namespace.def]p8
中进一步指出的那样,封闭命名空间中的名称查找将包括在任何inline
命名空间中找到的名称,但是嵌套内联命名空间的成员仍然是它们自己的实体。
<一口>一口>
7.3.1p8
命名空间定义[namespace.def]
具体来说,内联命名空间和它的封闭命名空间都被添加到参数依赖查找(3.4.2)中使用的关联命名空间集中,并且将命名内联命名空间的using-direction(7.3.4)隐式插入到封闭命名空间中,就像未命名命名空间(7.3.1.1)一样。
此外,内联命名空间的每个成员随后都可以显式实例化(14.7.2)或显式特化(14.7.3),就像它是封闭命名空间的成员一样。最后,通过显式限定(3.4.3.2)在封闭的命名空间中查找名称,将包括using指令引入的内联命名空间的成员,即使在封闭的命名空间中有该名称的声明。
添加的名称不被视为先前声明的实体的重新声明,它们是嵌套声明区域中的附加名称,在名称查找期间被带入封闭的命名空间。
注意:依靠编译器发出odr违规的诊断是不安全的,主要是因为标准明确声明"不需要诊断"如果应用程序违反了
[basic.def.odr].
设置的规则
进一步的细节可以在Matthieu M.对这篇文章的评论中找到。
- 嵌套的匿名命名空间
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- Boost.Python :C++模板类型匹配的嵌套命名空间
- 如何访问嵌套在命名命名空间中的未命名命名空间变量?
- 是否可以在相同的命名空间中,但在不同的嵌套项目中定义具有相同名称的类
- 如何从嵌套在命名空间中的类调用成员函数?
- 使用 astyle 在一行上格式化C++中的嵌套命名空间
- 这个嵌套的名称空间定义有什么作用
- 为什么C 允许具有相同名称的嵌套名称空间
- 用于更简洁代码的嵌套命名空间
- C++嵌套的"命名空间""使用"名称查找首选项顺序
- 在嵌套名称空间范围中使用名称空间的正确方法
- 是否可以避免在前向声明中使用嵌套命名空间?
- C 使用名称空间嵌套的同一名称空间
- C++对名称空间和别名的混淆:没有嵌套和使用指令
- 正在使用未定义的嵌套 std 和 posix 命名空间
- C++嵌套类函数返回类型和命名空间
- 尽管包含头文件,但仍找不到嵌套命名空间
- C 11无法解析嵌套名称空间