名称空间与包含的名称相同 class,gcc 可以,clang 不行
Namespace having the same name as contained class, ok for gcc, not ok for clang
考虑代码:
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()
不是一个完整的答案,但这是一个明确的情况,表明即使声明使用命名空间,对于与命名空间同名的对象,您也需要声明命名空间。
#include <iostream>
#include <string>
namespace test
{
void function1(void){std::cout << "Function inside the namespace" << std::endl;}
class test
{
public:
static void function1(void){std::cout << "Function inside the class" << std::endl;}
};
};
using namespace test;
int main()
{
function1();
test::function1();
test::test::function1();
}
输出 (GCC 4.9.2)
"Function inside the namespace"
"Function inside the namespace"
"Function inside the class"
[namespace.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
,命名空间和 class 都会被考虑。但是,命名空间的名称驻留在全局命名空间中,而 class 驻留在命名空间 X
中;因此上面的引用适用,因此 Clang 是正确的。 (这也发生在只写 X
时,很明显)。
::X
消除了这种歧义。查找不再进入命名空间。 [namespace.qual]/2:
For a namespace X
and name m
, the namespace-qualified lookup set
S(X, m) is defined as follows: Let
S0(X, m) be the set of all declarations of m
in X
and the inline namespace set of X
(7.3.1). If S0(X, m) is
not empty, S(X, m) is S0(X, m); otherwise, […]
这里,X
是全局命名空间,m
是"X"。很明显,我们的命名空间的声明是找到了,所以这里查找是肯定的。
考虑代码:
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()
不是一个完整的答案,但这是一个明确的情况,表明即使声明使用命名空间,对于与命名空间同名的对象,您也需要声明命名空间。
#include <iostream>
#include <string>
namespace test
{
void function1(void){std::cout << "Function inside the namespace" << std::endl;}
class test
{
public:
static void function1(void){std::cout << "Function inside the class" << std::endl;}
};
};
using namespace test;
int main()
{
function1();
test::function1();
test::test::function1();
}
输出 (GCC 4.9.2)
"Function inside the namespace"
"Function inside the namespace"
"Function inside the class"
[namespace.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
,命名空间和 class 都会被考虑。但是,命名空间的名称驻留在全局命名空间中,而 class 驻留在命名空间 X
中;因此上面的引用适用,因此 Clang 是正确的。 (这也发生在只写 X
时,很明显)。
::X
消除了这种歧义。查找不再进入命名空间。 [namespace.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"。很明显,我们的命名空间的声明是找到了,所以这里查找是肯定的。