嵌套匿名命名空间

Zac*_*Saw 5 c++ language-lawyer

在 C++ 中,通过以下方式声明嵌套匿名命名空间是合法的:

namespace {
    namespace {
        struct Foo
        {
        };
    }
}

namespace {    
    struct Foo // SAME IDENTIFIER AS <unnamed>::<unnamed>::Foo!!!
    {
    };
}
Run Code Online (Sandbox Code Playgroud)

但是,如何使用显式类型化的 Foo 声明标识符以避免歧义?

已编辑 - 对于所有没有阅读该问题的人。

ps 我无意使用这种结构,但我需要了解是否可以消除 Foo 的歧义,以防有人发现它的合法用途。我的编译器扩展需要处理所有情况。

Jes*_*ood 4

C++ 标准在 7.3.1.1p1 中非常清楚地说明了这一点:

未命名命名空间定义的行为就好像它被替换为

inline(opt) namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
Run Code Online (Sandbox Code Playgroud)

其中,当且仅当 inline 出现在未命名命名空间定义中时,翻译单元中所有出现的 unique 都会被相同的标识符替换,并且该标识符与整个程序中的所有其他标识符不同。

因此,从上面,我们知道您的代码实际上会翻译为以下内容:

namespace unique1 {}
using namespace unique1;
namespace unique1 {
    namespace unique2 {}
    using namespace unique2;
    namespace unique2 {

        struct Foo
        {
        };

    }
}

namespace unique3 {}
using namespace unique3;
namespace unique3 {

    struct Foo
    {
    };

}
Run Code Online (Sandbox Code Playgroud)

因此Foo由于.​​​ namespace unique1Foousing namespace unique3;我错了。通过下面的评论进行更正。

然后从 7.3.4p4 开始:

对于非限定查找 (3.4.1),using 指令是传递的:如果作用域包含一个 using 指令,该 using 指令指定了本身包含 using 指令的第二个命名空间,则效果就好像来自第二个命名空间的 using 指令也一样出现在第一个。

因此,当您引用 时Foo,它可能意味着unique1::unique2::Foounique3::Foo,这是一个错误请注意,另一个答案说:has hidden unique name that cannot be accessed。这是不正确的,由于 using 指令可以访问它们,只是两个名称都是可见的。

但是,通过在前面添加范围解析运算符,您可以::访问,因为以下原因:Foounique3::Foo

从 3.4.3.2p2 开始:

对于命名空间 X 和名称 m,命名空间限定查找集 S(X,m) 定义如下:令 S0(X,m) 为 X 中 m 的所有声明和 X 的内联命名空间集 ( 7.3.1)。若S0(X,m)不为空,则S(X,m)为S0(X,m);否则,S(X,m) 是 X 及其内联命名空间集中使用指令指定的所有命名空间 Ni 的 S(Ni,m) 的并集

强调的部分表示using-directives in X,在您的情况下意味着using namespace unique1;using namespace unique3;,因此命名空间限定的查找集看起来像这样:S(unique3::Foo),这意味着unique1::unique2::Foo 包含在该集合中,因此不是错误。