以下代码:
#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;
}由于以下原因,...does没有使用g++ (版本5.1.0和5.3.0)进行编译:
错误:部分专门化并不比主模板更专门化,因为它用包展开替换多个参数。
...but使用clang进行编译。
是否允许宣布这种局部的专门化?
附带注意:实际上,专门化是危险的,因为A<0, int>无法使用这两个编译器进行编译(模板参数的错误数量)。
发布于 2016-03-29 19:33:04
gcc是对的,代码是错误的,因为专业并不是更专业化.
来自temp.class.spec的规则是(作为链接的DR 1495,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然后遍历偏序规则。这又涉及到为每个模板参数合成新的类型/值,并查看演绎是否可以在任何方向上成功。
当然,专门化的演绎在主用户中失败(由于N和0)。在另一个方向,从temp.deduct.partial
如果从函数参数包转换了
A,而P不是参数包,则类型推断失败。
由于我们试图从一个包中推断出T first,推论也会在这个方向上失败。这意味着合成的函数模板中没有一个比其他模板更专业化,这反过来意味着类模板专门化并不比主模板更专业化。因此,gcc拒绝的说法是正确的。
https://stackoverflow.com/questions/36293088
复制相似问题