Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板类继承名称空间的名称查找_C++_Templates - Fatal编程技术网

C++ 模板类继承名称空间的名称查找

C++ 模板类继承名称空间的名称查找,c++,templates,C++,Templates,我最终设法将我的单片模板库编译失败归结为一个简单的测试用例。MSVC不同意Clang和GCC关于代码格式错误的意见,主要原因是名称查找。不幸的是,我不擅长阅读C++规范,当涉及到一致性时,我倾向于相信Clang和GCC,但是你能帮我找到相关的部分,以便我可以提交一个bug吗? namespace A { template <int _I, int _II> struct X {}; } namespace B { template <int _J>

我最终设法将我的单片模板库编译失败归结为一个简单的测试用例。MSVC不同意Clang和GCC关于代码格式错误的意见,主要原因是名称查找。不幸的是,我不擅长阅读C++规范,当涉及到一致性时,我倾向于相信Clang和GCC,但是你能帮我找到相关的部分,以便我可以提交一个bug吗?
namespace A
{
    template <int _I, int _II>
    struct X {};
}

namespace B
{
    template <int _J>
    struct X {};

    // Clang: OK
    // GCC: OK
    // MSVC: OK
    template <int _K>
    struct Y
    {
        Y(const A::X<_K, _K>&,
          const X<_K>&) {}
    };

    // Clang: OK
    // GCC: OK
    // MSVC: ERROR
    template <int _K>
    struct Z : A::X<_K, _K>
    {
        Z(const A::X<_K, _K>&,
          const X<_K>&) {}
    };

    // Clang: ERROR
    // GCC: ERROR
    // MSVC: ERROR
    struct Q : A::X<1, 1>
    {
        Q(const A::X<1, 1>&,
          const X<1>&) {}
    };
}

int main()
{
    A::X<1, 1> ax;
    B::X<1> bx;

    B::Z<1> bz(ax, bx);

    return 0;
}
名称空间A
{
模板
结构X{};
}
命名空间B
{
模板
结构X{};
//叮当声:好的
//GCC:好的
//MSVC:好的
模板
结构
{
Y(常数A::X&,
常数X&{}
};
//叮当声:好的
//GCC:好的
//MSVC:错误
模板
结构Z:A::X
{
Z(常数A::X&,
常数X&{}
};
//叮当声:错误
//GCC:错误
//MSVC:错误
结构Q:A::X
{
Q(常数A::X&,
常数X&{}
};
}
int main()
{
A::X ax;
B::X bx;
B::zbz(ax,bx);
返回0;
}
三个案例是:

  • 这没什么了不起的。这两种编译器都可以很好地编译
  • 编译错误源于Z的CTOR的第二个参数,X没有足够的模板参数。由名称查找决定我应该引用哪个X。据我从阅读中了解,当涉及到非限定名称查找时,从类继承不应将其名称引入范围
  • 如果类Q本身不是模板,则所有编译器都会拒绝它。这是我完全失利的部分。为什么类是否是模板很重要

  • 这是怎么回事?

    gcc的错误消息提供了线索:

    38 : error: wrong number of template arguments (1, should be 2)
    const X<1>&) {}
    ^
    4 : note: provided for 'template<int _I, int _II> struct A::X'
    struct X {};
    ^
    
    38:错误:模板参数的数量错误(1,应该是2)
    常数X&{}
    ^
    4:注意:为“模板结构A::X”提供
    结构X{};
    ^
    
    这是怎么回事

    模板类不是代码。这是一个创建代码的方法。使用时,两阶段查找将处理
    Z
    的定义(此时最好有
    X
    可用)

    Q
    是一个具体的类,因此不涉及两阶段查找
    X
    必须存在于该点,但它不存在


    和以往一样,clang和gcc是正确的。MSVC不符合要求。

    您遇到的问题是注入的类名。来自[课堂]:

    类名也被插入到类本身的作用域中;这称为注入的类名。 出于访问检查的目的,注入的类名被视为公共成员名

    对于类定义中的非限定查找,第一个停止点位于类及其成员的范围内。来自[basic.lookup.unqual]:

    在成员函数体、默认参数、异常规范之外的类
    X
    定义中使用的名称, 非静态数据成员的大括号或同等初始值设定项或嵌套类定义应为 以以下方式之一声明:
    (7.1)-在类
    X
    中使用之前,或是
    X
    (10.2)的基类成员,或
    (7.2)-[…]

    我们正在寻找
    X
    。没有<代码> q:x:<代码>(<代码> q>代码>自己的作用域),但是有一个<代码>:::x::x/c>(基类范围),所以查找停止,我们从不考虑<代码> q>代码>的封闭命名空间。这就是为什么我们找到
    A::X
    而不是
    B::X

    使用
    Z
    ,情况有点不同。现在,基类是依赖类模板,非限定查找将不会在依赖基类中查找。从[临时部门]:

    在类或类模板的定义中,不检查依赖基类(14.6.2.1)的范围 在类模板或成员的定义点或 类模板或成员的实例化

    因此,虽然名称
    A::X::X
    存在,但不考虑它,因此继续查找封闭的名称空间并找到
    B::X


    在这两种情况下,gcc/clang都是正确的

    你想看这篇文章吗?我明白错误是怎么说的。我的问题是为什么它认为我指的是A::X?我在命名空间B中的类的上下文中说X,该类继承自命名空间a中的类。为什么X只是引用a::X,而非限定查找则会提出其他建议?“为什么类本身是否是模板很重要?”Meteohead重写道。所以你是说两阶段查找规则意味着第一次检查语法时不能检查函数名?即使MSVC没有正确地“跳过”第一阶段,在编译器到达Z时,A::X和B::X都已被解析,因此它拥有所有必要的信息,可以确保没有任何可疑之处。@当解析模板时,语法必须正确,任何已知存在的事物都必须如此。
    B::X
    存在于
    Q
    点处。。。如果将参数设置为
    B::X
    而不是
    X
    ,则代码将编译。旁注:此处使用的是一组保留标识符