考虑代码:
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 吐出错误:
error: 'X' is not a class, namespace, or enumeration Foo f()
error: reference to 'X' is ambiguous
根据 C++ 标准,代码在语法上是否有效?或者只是一个 gcc 错误?删除限定名称 X::X
并使用 Foo<X>
相反也让 gcc 窒息
error: template argument 1 is invalid Foo f()
最佳答案
[命名空间.udir]/6:
If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed.
对于 X::X
中的第一个 X
,命名空间和类都会被考虑。但是,命名空间的名称驻留在全局命名空间中,而类驻留在命名空间 X
中;因此上面的引用适用,因此 Clang 是正确的。 (显然,当只写 X
时也会发生这种情况)。
::X
消除了这种歧义。查找不再进入命名空间。 [命名空间.qual]/2:
For a namespace
X
and namem
, the namespace-qualified lookup set S(X, m) is defined as follows: Let S0(X, m) be the set of all declarations ofm
inX
and the inline namespace set ofX
(7.3.1). If S0(X, m) is not empty, S(X, m) is S0(X, m); otherwise, […]
这里,X
是全局命名空间,m
是“X”。很明显,我们的命名空间的声明找到了,所以这里查找是确定的。
关于c++ - 命名空间与包含的类同名,gcc 可以,clang 不行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33313853/