内部命名空间名称与全局命名空间名称匹配时的多义性
Ambiguity when inner namespace name matches a global namespace name
语言律师,注意!
我有以下代码:
namespace conflicting
{
struct Foo {};
}
namespace outer
{
namespace conflicting
{
struct Bar {};
}
}
using namespace outer;
int main()
{
conflicting::Bar b;
return 0;
}
使用 g++ 4.8.2,我在尝试编译时收到以下错误:
t.cpp: In function ‘int main()’:
t.cpp:18:5: error: reference to ‘conflicting’ is ambiguous
conflicting::Bar b;
^
t.cpp:2:1: note: candidates are: namespace conflicting { }
{
^
t.cpp:9:5: note: namespace outer::conflicting { }
{
^
t.cpp:18:5: error: reference to ‘conflicting’ is ambiguous
conflicting::Bar b;
^
t.cpp:2:1: note: candidates are: namespace conflicting { }
{
^
t.cpp:9:5: note: namespace outer::conflicting { }
{
^
t.cpp:18:22: error: expected ‘;’ before ‘b’
conflicting::Bar b;
有人可以向我解释为什么会发生此错误(也许参考标准的一部分)?
你用conflicting::
限定了一个名字,所以编译器需要去那个范围内寻找Bar
......但是哪个范围呢?它可以引用两个不同的,::conflicting
或outer::conflicting
由于 using-指令,可以在没有 outer::
前缀的情况下引用它们。
快速摘要:要使 X::m 成为限定 id,X 需要唯一地引用单个命名空间。
如果conflicting
是"命名命名空间的嵌套名称说明符",conflicting::Bar
是限定 id,Bar
是"该命名空间的成员的名称(或由 using-指令显示的命名空间成员的名称)"(所有引用都是对 N3337 的引用,所有强调都是我的):
5.1.1 一般规定
- 一个 :: 或命名命名空间 (7.3) 的嵌套名称说明符,在这两种情况下,后跟该命名空间成员的名称(或由 using-指令显示的命名空间成员的名称)是限定 id;3.4.3.2 描述了出现在限定 ID 中的命名空间成员的名称查找。结果 是成员。结果的类型是成员的类型。如果成员是函数或变量,则结果为左值,否则为属性值。
第 3.4 节描述了名称查找的过程,该过程要求名称查找找到名称的明确声明(重载函数是例外):
3.4 名称查找
名称
- 查找规则统一适用于所有名称(包括 typedef-names (7.1.3)、命名空间名称 (7.3) 和类名 (9.1)),只要语法允许在特定规则讨论的上下文中使用此类名称。名称查找将名称的使用与该名称的声明 (3.1) 相关联。名称查找应找到名称的明确声明(见 10.2)。如果名称查找发现名称是函数名称,则名称查找可能会将多个声明与名称相关联;声明被称为形成一组重载函数 (13.1)。重载解析 (13.3) 在名称查找成功后发生。访问规则(第 11 条)仅在名称查找和函数重载解析(如果适用)成功后才会被考虑。只有在名称查找、函数重载解析(如果适用)和访问检查成功之后,名称声明才会引入的属性进一步用于表达式处理(第 5 条)。
第 3.4.3.2 节的措辞清楚地表明命名空间必须是唯一的:
3.4.3.2 命名空间成员 [命名空间.qual]
对于命名空间 X 和名称 m,命名空间限定的查找集 S(X,m
- ) 定义如下:设 S'(X,m) 是 X 中 m 的所有声明和 X (7.3.1) 的内联命名空间集的集合。如果 S'(X,m) 不为空,则 S(X,m) 为 S'(X,m);否则,S(X,m) 是 S(N_i,m) 的并集,用于通过 X 中的 using 指令及其内联命名空间集提名的所有命名空间 Ni。
此描述假定 X 是唯一的,因为它没有描述遍历一组可能的命名空间以查找 m 的任何过程。
由于编译器无法确定将哪个conflicting
命名空间用作命名空间成员查找的起点,因此会给出错误。
希望有帮助。
不需要语言法律!一旦outer
命名空间引入当前命名空间(通过using
它),它的所有名称都变得可见。所以现在你有一个冲突。
这就是为什么我强烈反对using
命名空间的做法。命名空间的发明是有原因的,原因是为了防止此类问题。
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- CUDA内核和数学函数的显式命名空间
- 嵌套的匿名命名空间
- CMakeLists.txt中的命名空间表示法
- 类是C++中的命名空间吗
- 在命名空间中使用全局命名空间中的函数
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 是否可以将函数导入命名空间,但不能导出它?
- C++ C++类中的命名空间降级
- 如何使用 soong 命名空间来有条件地编译模块
- 使用 Clang++ 有没有办法将文件作为命名空间等包含?
- 使用 make 编译 MPI,几个命名空间错误,例如"错误:未知类型名称'使用'?
- 如何通过命名空间调用非静态方法
- 内部命名空间名称与全局命名空间名称匹配时的多义性