考虑代码:
template<typename T>
class Foo{};
namespace X
{
class X{};
}
using namespace X; // now both class X and namespace X are visible
Foo<X::X> f()
{
return {};
}
int main() {}
gcc5.2编译代码时没有任何错误。然而clang吐出错误:
错误:'X'不是类,命名空间或枚举 Foo f()
错误:对'X'的引用含糊不清
根据C ++标准,代码在语法上是否有效?或者只是一个gcc bug?删除限定名称X::X
并使用Foo<X>
代替gcc choke
错误:模板参数1无效 Foo f()
答案 0 :(得分:3)
[namespace.udir] / 6:
如果名称查找找到两个不同的名称声明 名称空间,并且声明不会声明相同的实体 没有声明功能,名称的使用是不正确的。
对于X
中的第一个X::X
,将考虑命名空间和类。但是,名称空间的名称驻留在全局名称空间中,而类位于名称空间X
中;因此,上述引用适用,因此Clang是正确的。 (当明确写出X
时也会出现这种情况。)
::X
消除了这种歧义。 Lookup不再进入命名空间。 [namespace.qual] / 2:
对于名称空间
X
和名称m
,名称空间限定的查找集 S(X,m)的定义如下:设 S 0 (X,m)是m
中X
的所有声明的集合,X
的内联命名空间集合(7.3.1)。 如果 S 0 (X,m)是 非空, S(X,m)是 S 0 (X,m); 否则,[...]
此处,X
是全局命名空间,m
是&#34; X&#34;。很明显,我们找到了命名空间的声明,所以在这里查找是明确的。
答案 1 :(得分:1)
不是一个完整的答案,但这是一个明显的情况,甚至表明使用命名空间,对于与您需要声明命名空间的名称空间同名的对象。
"Function inside the namespace"
"Function inside the namespace"
"Function inside the class"
输出(GCC 4.9.2)
public static boolean dictHasWord(String str){
for(int i = 0; i < dictionary.length; i++){
if(str.equals(dictionary[i])){
return true;
}
}
return false;
}