2014-09-27 97 views
3

考虑下面的两段代码:全球具名命名空间歧义VS嵌套具名命名空间歧义

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 Afoo的用法在方int main()是不明确的,而在Snippet B它不是。为什么会这样?


相关:Anonymous Namespace Ambiguity

+1

A是不合格的查询; B是合格的查找。不同的规则。 – 2014-09-27 03:40:17

+0

我同意T.C,事实上,如果你简单地添加'void bar(){std :: cout << foo <<'\ n'; }'命名空间'A'内,但要警告*你添加它是相关的。 [** This Works **](http://ideone.com/azVxvU),例如,[** this not **](http://ideone.com/zt9NPA)。 – WhozCraig 2014-09-27 03:54:52

回答

5

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

一种无名名称空间定义表现为如果它被替换为

inline_opt namespace unique { /* empty body */ } 
using namespace unique ; 
namespace unique { namespace-body } 

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

特别要注意的是,不具名命名空间中的声明是在周边范围内通过使用指示符using namespace unique;可见。

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

2从提名的命名空间中的声明一使用指示符 成为封闭一个命名空间可见using指令;见 7.3.4。出于在3.4.1中描述的非限定名称查找规则的目的,来自 使用指令指定的名称空间的声明被认为是该封闭名称空间的成员。

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

在片段B中,A::foo是合格的,因此适用合格的名称查找规则。由于A是一个名称空间,所以适用的子条款是§3.4.3.2[namespace.qual]。作为与此有关,该规则在该条款的第2款规定:

对于一个命名空间X和名称m,命名空间限定查找设置 S(X,m)定义如下:设S'(X,m)是集合所有 的m的声明X和内联命名空间集X (7.3.1)。如果S'(X,m)不为空,则S(X,m)S'(X,m);否则, S(X,m)S(Ni,m)获提名 所有命名空间Ni通过using指令X其内嵌的命名空间集中的工会。

换句话说,合格的名称查找认为通过using指令提名的命名空间只有名字没有在指定的命名空间和其内嵌的命名空间集中找到。在这里,名称foo位于名称空间A中,因此未考虑使用指令提名的未命名名称空间,因此不存在歧义。

如果您在代码片段A中写入::foo而不是foo,那么将改为使用合格的查找规则,而且这将再次成为不含糊之处。