C++ 模板类继承名称空间的名称查找
我最终设法将我的单片模板库编译失败归结为一个简单的测试用例。MSVC不同意Clang和GCC关于代码格式错误的意见,主要原因是名称查找。不幸的是,我不擅长阅读C++规范,当涉及到一致性时,我倾向于相信Clang和GCC,但是你能帮我找到相关的部分,以便我可以提交一个bug吗?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>
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;
}
三个案例是:
这是怎么回事?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
,则代码将编译。旁注:此处使用的是一组保留标识符