嵌套的匿名命名空间

时间:2012-10-25 23:38:39

标签: c++ language-lawyer

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

namespace {
    namespace {
        struct Foo
        {
        };
    }
}

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

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

已编辑 - 对于所有未阅读此问题的人。

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

2 个答案:

答案 0 :(得分:3)

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

  

unnamed-namespace-definition的行为就像它被

替换一样
inline(opt) namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
  

当且仅当内联出现在内容中时,内联出现   unnamed-namespace-definition,a中所有出现的唯一   翻译单元由相同的标识符替换,并且这个   标识符与整个程序中的所有其他标识符不同。

从上面我们知道您的代码实际上转换为以下内容:

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 unique1 ,并且可以在全局命名空间中访问第二个Foo,因为{ {1}}。我错了。通过以下评论进行更正。

然后从7.3.4p4开始:

  

对于非限定查找(3.4.1),using-directive是可传递的:if   范围包含指定第二个命名空间的using-directive   它本身包含using-directives,效果就像是   第二个命名空间中的using-directives也出现在第一个命名空间中。

因此,当您引用using namespace unique3;时,它可能意味着Foounique1::unique2::Foo,这是错误请注意另一个答案是:unique3::Foo。这是不正确,由于使用指令,可以访问它们,只是两个名称都可见。

但是,通过将范围解析运算符has hidden unique name that cannot be accessed添加到::可以访问Foo,原因如下:< / p>

从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及其内联命名空间集

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

答案 1 :(得分:0)

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

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

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

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