C++ gcc与带有可变参数加上相同类型额外参数的部分特殊化上的clang行为
以下代码:C++ gcc与带有可变参数加上相同类型额外参数的部分特殊化上的clang行为,c++,c++11,variadic-templates,template-specialization,C++,C++11,Variadic Templates,Template Specialization,以下代码: #include <cstddef> template <size_t N, typename T, T first, T... rest> struct A { }; template<typename T, T... args> struct A<0, T, args...> { }; int main () { A<0, int, 1
#include <cstddef>
template <size_t N,
typename T,
T first,
T... rest>
struct A {
};
template<typename T,
T... args>
struct A<0, T, args...> {
};
int main () {
A<0, int, 1> a0;
A<2, int, 1, 2> a2;
return 0;
}
#包括
模板
结构A{
};
模板
结构A{
};
int main(){
a0;
A a2;
返回0;
}
…未使用g++
(版本5.1.0
和5.3.0
)编译,原因是:
错误:部分专用化并不比主模板更专用,因为它用包扩展替换多个参数
…但编译时会发出clang
是否允许声明此类局部专业化
旁注:实际上,专门化是危险的,因为
A
无法同时使用两个编译器进行编译(模板参数的数目错误)。gcc是正确的,代码格式错误,因为专门化实际上并没有更专门化
[temp.class.spec]中的规则是(作为链接h/t t.C.的结果): 在类模板部分专门化的参数列表中,以下限制适用:[……]专门化应比主模板(14.5.5.2)更专业化 为了确定这一点,我们将重写两个合成函数模板:
template <size_t N, class T, T first, T... rest>
void __f(A<N, T, first, rest...> ); // primary
template <class T, T... args>
void __f(A<0, T, args...> ); // specialization
模板
无效_uf(A);//主要的,重要的
模板
无效_uf(A);//专业化
然后检查偏序规则。这又涉及到为每个模板参数合成新的类型/值,并查看推导是否可以在任一方向上成功
明确地说,专业化的推导在主代码中失败(由于N
vs0
)。在另一个方向,从[临时扣除部分]:
如果A
是从函数参数包转换而来,并且p
不是参数包,则类型推断失败
由于我们试图先根据一个包推断出T
,所以这个方向的推断也失败了。这意味着两个合成函数模板都不比其他模板更专业化,这反过来意味着类模板专业化并不比主模板更专业化。因此,gcc拒绝是正确的。考虑:
template <class T, T first, T... rest>
struct X{};
template<class T, T... rest>
struct X<T, rest...>{};
要允许
A
,必须更改第一个模板。现在进行专门化已经太晚了。@Jarod42是的,我知道这样的模板实例化是错误的,我只是想问一下只使用T。。。args
在g++
中引发错误,但不是clang
(重新组织问题以使其更清楚)。GCC是正确的。这是一个格式错误的per(有些不足为奇,因为它是由GCC的维护人员报告的)。@T.C.哦,它不是一个函数参数包,没关系。
//specialization
template<typename T,
T first,
T... args>
struct A<0, T, first, args...> {
};