全局未命名的命名空间歧义与嵌套的未命名的命名空间歧义

时间:2014-09-27 03:12:58

标签: c++ namespaces ambiguous

请考虑以下两个代码段:

Snippet A

#include <iostream>

namespace
{
    bool foo = false;
}

bool foo = true;

int main()
{
    std::cout << foo << std::endl;
}

Snippet B

#include <iostream>

namespace A
{
    namespace
    {
        bool foo = false;
    }

    bool foo = true;
}

int main()
{
    std::cout << A::foo << std::endl;
}

Snippet A中,fooint main()的使用情况不明确,而在Snippet B中则不然。为什么会这样?


相关:Anonymous Namespace Ambiguity

1 个答案:

答案 0 :(得分:5)

未命名的命名空间的行为在§7.3.1.1[namespace.unnamed] / p1中指定:

  

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

取代一样
inline_opt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }
     

当且仅当inline出现在unique中时才出现    unnamed-namespace-definition ,翻译单元中所有出现的using namespace unique;都被相同的标识符替换,   标识符与整个程序中的所有其他标识符不同。

请特别注意,未命名的命名空间内的声明通过 using-directive foo在周围的范围内可见。

在Snippet A中,foo是不合格的,因此编译器执行非限定名称查找(§3.4.1[basic.lookup.unqual])。这里相关的是子条款的第2段:

  

2 using-directive 指定的命名空间声明   在包含 using-directive 的命名空间中可见;看到   7.3.4。出于3.4.1中描述的非限定名称查找规则的目的,由名称空间提名的声明    using-directive 被认为是该封闭命名空间的成员。

因此,非限定名称查找会找到A::foo的声明,并且名称不明确。

在代码段B中,A是合格的,因此适用了限定名称查找规则。由于X是命名空间,因此适用的子句是§3.4.3.2[namespace.qual]。与此相关,该规则在该子条款第2款中规定:

  

对于名称空间m和名称S(X,m),名称空间限定的查找集   S'(X,m)的定义如下:让m成为所有的集合   XX的声明以及S'(X,m)的内联命名空间集   (7.3.1)。如果S(X,m)不为空,则S'(X,m)S(X,m);除此以外,   S(Ni,m)Ni的联盟,用于提名所有名称空间X   通过foo中的 using-directives 及其内联命名空间集。

换句话说,只有在指定的命名空间及其内联命名空间集中找不到该名称时,限定名称查找才会考虑由 using-directives 指定的命名空间。这里,名称A位于名称空间::foo中,因此不考虑 using-directive 指定的未命名名称空间,并且没有歧义。

如果您在代码段A中写foo而不是{{1}},那么将会应用合格的查找规则,而且再次没有歧义。