2

考虑以下代码:

struct foo {
    typedef int bar;
};

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

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

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

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

就像是:

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

2 回答 2

10

C++11 标准的第 7.3.1/2 段简单地禁止:

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

关于您的这份声明:

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

这是不正确的。第 7.3.2/4 段(尤其是最后一句)告诉您为什么它似乎“工作”,尽管您的程序格式不正确:

名称空间名称名称空间别名不应被声明为同一声明区域中任何其他实体的名称。在全局范围内定义的命名空间名称不得声明为程序的任何全局范围内的任何其他实体的名称。不同翻译单元中的声明违反此规则不需要诊断

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

于 2013-05-27T12:04:39.140 回答
2

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

不,它没有。根据 C++11 3.3.1/4,为两个不同的实体声明相同的名称会给出未定义的行为:

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

(除了一些不包括给类和命名空间同名的例外情况)。

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

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

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

于 2013-05-27T12:20:08.403 回答