命名空间与包含的类同名,gcc可以,clang不行

Namespace having the same name as contained class, ok for gcc, not ok for clang

本文关键字:gcc 可以 clang 不行 包含 命名空间      更新时间:2023-10-16

考虑以下代码:

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阻塞也

error:模板参数1无效Foo f ()

[namspace .udir]/6:

如果名称查找在两个不同的名称空间和声明不声明相同的实体如果不是声明函数,使用名称是错误的。

对于X::X中的第一个X,同时考虑命名空间和类。但是,命名空间的名称驻留在全局命名空间中,而类驻留在命名空间X中;因此上述引用适用,因此Clang是正确的。(显然,当只写X时也会出现这种情况)。

::X消除了这种歧义。查找不再进入名称空间。(namespace.qual)/2:

对于名称空间X和名称m,名称空间限定的查找集S(X, m)定义如下S0(X, m)Xm的所有声明的集合和X的内联命名空间集合(7.3.1)。如果S0(X, m)是非空, S (X, m) S <子> 0 (X,米), 否则,[…]

这里,X是全局命名空间,m是"X"。显然,找到了名称空间的声明,因此这里的查找是明确的。

不是一个完整的答案,但这是一个清楚的情况,即使声明使用名称空间,对于与名称空间同名的对象,您也需要声明名称空间。

#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"