在下面的代码中:
template <int...> struct IndexSequence {};
template <int, int, typename, int...> struct Helper;
template <int Start, typename Coefficients, int... Is>
struct Helper<Start, Start, Coefficients, Is...> {
using type = IndexSequence<Is...>;
};
template <int Start, int N, int... As, int... Is>
struct Helper<Start, N, IndexSequence<As...>, Is...> :
Helper<Start, N-1, IndexSequence<As...>, N-1, Is...> {};
int main() {
Helper<2,5, IndexSequence<1,2,3>>::type a;
}
我收到编译错误:
ambiguous class template instantiation for 'struct Helper<2, 2, IndexSequence<1, 2, 3>, 2, 3, 4>'
我认为它将解决专业化问题
template <int Start, typename Coefficients, int... Is>
struct Helper<Start, Start, Coefficients, Is...> {
using type = IndexSequence<Is...>;
};
但我想它也在读
struct Helper<Start, N, IndexSequence<As...>, Is...> :
Helper<Start, N-1, IndexSequence<As...>, N-1, Is...> {};
那么如何解决这种歧义呢?
本质上的问题是,没有一个专业比另一个专业更专业。
在决定也选择哪个局部专业化时,首先将这些专业化与参数进行匹配,以检查它们是否可行(在这里都是可行的)。如果可行的话,那么要决定选择哪一个,我们必须检查哪个比其他任何一个更专业。此过程称为“部分排序”,它是通过比较专用模板“参数”(彼此之间(即中的模板参数Helper<...>
))进行比较的-一个模板被用作参数模板,另一个是参数模板。参数模板提供类型,然后执行推导以查看是否可以根据参数模板的类型推导参数模板中的模板参数。
template <int Start, typename Coefficients, int... Is>
struct Helper<Start, Start, Coefficients, Is...>
// ^^^^^ ^^^^^ ^^^^^^^^^^^^ ^^^^^
// A: 1 2 3 4
template <int Start, int N, int... As, int... Is>
struct Helper<Start, N, IndexSequence<As...>, Is...>
// ^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^
// B: 1 2 3 4
对于自变量模板的每个自变量,将为每个模板参数组成一些唯一值,并将其替换为自变量。然后,将这些转换后的参数传递到参数模板,以检查推导是成功还是失败。举个例子:
int
可以从推导得出int
)现在让我们看一下关键的推论:
B2是针对A2推导的,但是由于我们同时针对Start
和使用了唯一值N
,因此Start
在模板A中的推导不一致,这意味着推导在这里失败。
A3是针对B3推导的,但由于Coefficients
是某些唯一类型(不是IndexSequence
!的特殊化),因此推导再次失败。
推论在两个方向上至少失败一次:因此,没有一个模板在整体上比另一个模板更专业。
通过将第一个特殊化写为
template <int Start, int... As, int... Is>
struct Helper<Start, Start, IndexSequence<As...>, Is...> {
using type = IndexSequence<Is...>;
};
现在,以上失败的第二个推论不再失败。仅将专业化B作为参数模板的那个。这意味着B更专业,因此被选中。
演示。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句