考虑以下代码:
struct foo {
typedef int bar;
};
namespace foo {
class baz {
/* code */
};
}
这是分布在我必须处理的代码库上,它有时会起作用,我不明白如何。
只要命名空间和类不在同一个源中(在预处理之后)就可以工作(我理解那部分)。但是,如果突然将命名空间和类都被预处理器拖入同一个编译单元,它(可能)会发生冲突(我不知道是否会在源中发生这种情况)。
是否存在允许编译器始终正确解析代码结构的约定?最合乎逻辑的是禁止名称空间和类具有相同的符号。应用的编码风格允许使用类冲突命名空间,虽然模糊不清,因此我更倾向于告诉编译器使用而不是更改编码约定。
类似的东西:
use_namespace(foo)::baz b;
use_class(foo) b;
答案 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:
为两个不同的实体声明相同的名称会产生未定义的行为在单个声明性区域中给出一组声明,每个声明都指定相同的非限定名称,它们都应引用同一个实体
(有些例外情况不包括为类和命名空间赋予相同的名称)。
由于声明是在单独的翻译单元中,因此许多编译器无法诊断错误,因此它似乎可以正常工作。
但是,如果突然命名空间和类被预处理器拖入同一个编译单元,它(可能)会发生冲突(我不知道是否在源中发生过这种情况)。
现在他们在同一个翻译单元中,可以诊断出错误。