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

时间:2013-05-27 11:59:55

标签: c++ c++11

考虑以下代码:

struct foo {
    typedef int bar;
};

namespace foo {
    class baz {
        /* code */
    };
}

这是分布在我必须处理的代码库上,它有时会起作用,我不明白如何。

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

是否存在允许编译器始终正确解析代码结构的约定?最合乎逻辑的是禁止名称空间和类具有相同的符号。应用的编码风格允许使用类冲突命名空间,虽然模糊不清,因此我更倾向于告诉编译器使用而不是更改编码约定。

类似的东西:

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

2 个答案:

答案 0 :(得分:10)

C ++ 11标准的第7.3.1 / 2段仅禁止:

  

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

关于你的陈述:

  

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

这是不正确的。第7.3.2 / 4段(特别是最后一句)告诉你为什么似乎“工作”,虽然你的程序是不正确的:

  

namespace-name namespace-alias 不得声明为同一个其他实体的名称   声明区域。在全局范围定义的 namespace-name 不应声明为any的名称   该计划的任何全球范围内的其他实体。 违反此规则不需要诊断   不同翻译单位的声明

这意味着您正在使用的代码库具有未定义的行为,这可能是一个可能以难以理解的方式爆炸的定时炸弹。

答案 1 :(得分:2)

  

只要命名空间和类不在同一个源中(在预处理之后)就可以工作(我理解那部分)。

不,不。根据C ++ 11 3.3.1 / 4:

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

在单个声明性区域中给出一组声明,每个声明都指定相同的非限定名称,它们都应引用同一个实体

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

由于声明是在单独的翻译单元中,因此许多编译器无法诊断错误,因此它似乎可以正常工作。

  

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

现在他们在同一个翻译单元中,可以诊断出错误。