如何消除名称相同的名称空间和类的歧义

how to disambiguate namespace and class with identical names

本文关键字:空间 歧义 何消      更新时间:2023-10-16

考虑以下代码:

struct foo {
    typedef int bar;
};
namespace foo {
    class baz {
        /* code */
    };
}

这是分布在我必须处理的代码库中,它有时会起作用,我不明白是怎么回事。

只要名称空间和类不出现在同一源(预处理后),它将工作(我理解这部分)。但是,如果突然命名空间和类都被预处理器拖到同一个编译单元中,它(可能)会发生冲突(我不知道这种情况是否发生在源代码中)。

是否有一个约定,允许编译器总是正确地解析代码结构?最合乎逻辑的做法是禁止名称空间和类使用相同的符号。应用的编码风格允许名称空间与类冲突,尽管存在歧义,因此我更喜欢一种方法来告诉编译器使用情况,而不是改变编码约定。

类似:

use_namespace(foo)::baz b; 
use_class(foo) b;

c++ 11标准第7.3.1/2段禁止:

original-namespace-definition 中的标识符不能在声明性中先前定义过原始命名空间定义出现的区域原始名称空间定义中的标识符命名空间的名称。随后,在该声明性区域中,它被视为原始命名空间

关于你方的声明:

只要命名空间和类不在同一个源中(预处理后),它就可以工作

这是不正确的。第7.3.2/4段(特别是最后一句)告诉你为什么看起来在"工作",尽管你的程序是病态的:

名称空间-name名称空间-alias不得声明为同一名称中任何其他实体的名称声明区域。在全局作用域中定义的命名空间名称不能声明为任何程序全局范围内的其他实体。不需要诊断违反此规则.

这意味着你正在处理的代码库有未定义的行为,这是一个潜在的定时炸弹,可能会以不可理解的方式爆炸。

只要命名空间和类不出现在同一个源中(预处理之后),它就会工作(我理解这部分)。

不,它没有。根据c++ 11 3.3.4/4:

,为两个不同的实体声明相同的名称会产生未定义的行为

给定一个声明区域中的一组声明,每个声明都指定了相同的非限定名,它们应该都指向同一个实体

(有一些例外,不包括为类和命名空间赋予相同的名称)。

由于声明在单独的翻译单元中,许多编译器无法诊断错误,因此它可能看起来有效。

但是,如果突然命名空间和类都被预处理器拖到同一个编译单元中,它(可能)会发生冲突(我不知道这种情况是否发生在源代码中)。

既然它们在同一个翻译单元中,就可以诊断错误了