5

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

namespace {
    namespace {
        struct Foo
        {
        };
    }
}

namespace {    
    struct Foo // SAME IDENTIFIER AS <unnamed>::<unnamed>::Foo!!!
    {
    };
}

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

已编辑——适用于所有未阅读该问题的人。

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

4

2 回答 2

4

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

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

inline(opt) namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

其中 inline 出现当且仅当它出现在 unnamed-namespace-definition 中时,翻译单元中所有出现的 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
    {
    };

}

因此,由于. Foo_ _ _ namespace unique1Foousing namespace unique3;我错了。通过下面的评论更正。

然后从 7.3.4p4:

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

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

但是,通过将范围解析运算符添加::Foo可以访问unique3::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) 是 S(Ni,m) 的并集,用于通过 X 中的 using 指令指定的所有命名空间 Ni 及其内联命名空间集

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

于 2012-10-25T23:59:23.660 回答
0

是的,这是完全合法的,因为它与任何东西都不矛盾。

未命名的命名空间在概念上等同于:

namespace <09FD8E6E-2DB6-4517-B62D-3B5A657DCC82>
{
  // ....
}

这意味着每个未命名的命名空间都隐藏着无法访问的唯一名称。

于 2012-10-25T23:40:06.517 回答