在C ++中以下列方式声明嵌套的匿名命名空间是合法的:
namespace {
namespace {
struct Foo
{
};
}
}
namespace {
struct Foo // SAME IDENTIFIER AS <unnamed>::<unnamed>::Foo!!!
{
};
}
但是,如何使用显式类型的Foo声明标识符以避免歧义?
已编辑 - 对于所有未阅读此问题的人。
P.S。我无意使用这种结构,但我需要了解是否有可能消除Foo的歧义,以防有人发现它的合法用途。我的编译器扩展需要处理所有情况。
答案 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;
时,它可能意味着Foo
或unique1::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 X
和using namespace unique1;
,因此命名空间限定的查找集如下所示:using namespace unique3;
,这意味着{ <1}} 不包含在集合中,因此不是错误。
答案 1 :(得分:0)
是的,这是完全合法的,因为它与任何内容都不矛盾。
未命名的命名空间在概念上等同于:
namespace <09FD8E6E-2DB6-4517-B62D-3B5A657DCC82>
{
// ....
}
意味着每个未命名的命名空间都隐藏了无法访问的唯一名称。