简体   繁体   English

如何解决这种歧义?

[英]How to resolve this ambiguity?

In the following code: 在以下代码中:

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;
}

I get the compile error: 我收到编译错误:

ambiguous class template instantiation for 'struct Helper<2, 2, IndexSequence<1, 2, 3>, 2, 3, 4>'

I figured it would resolve to the specialization 我认为它将解决专业化问题

template <int Start, typename Coefficients, int... Is>
struct Helper<Start, Start, Coefficients, Is...> {
    using type = IndexSequence<Is...>;
};

But I guess it is also reading 但我想它也在阅读

struct Helper<Start, N, IndexSequence<As...>, Is...> :
    Helper<Start, N-1, IndexSequence<As...>, N-1, Is...> {};

So how to resolve this ambiguity? 那么如何解决这种歧义呢?

The problem is essentially that none of the specializations is more specialized than the other. 问题基本上是没有一个专业化比另一个专业化更专业化。

When deciding which partial specialization too choose, the specializations are first matched against the arguments to check whether they are viable (here, both are). 在决定哪个部分特化也选择时,首先将特化与参数匹配以检查它们是否可行(这里两者都是)。 If multiple are viable, then to decide which one is to be chosen we have to check which one is more specialized than all others. 如果多个是可行的,那么要决定选择哪一个,我们必须检查哪一个比其他所有更专业。 This process is called "partial ordering" and done by comparing the specialized template "arguments" which each other (ie the template arguments in Helper<...> ) - one template is taken as the argument template, and the other is the parameter template. 这个过程称为“部分排序”,通过比较彼此的专用模板“参数”(即Helper<...>的模板参数)来完成 - 一个模板作为参数模板,另一个是参数模板。 The argument template provides the types, and deduction is performed to see if the template parameters from the parameter template can be deduced given the argument template's types. 参数模板提供类型,并且执行演绎以查看是否可以在给定参数模板的类型的情况下推导出参数模板中的模板参数。

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

For each argument of the argument template, some unique value is made up for each template parameter and substituted into the argument. 对于参数模板的每个参数,为每个模板参数组成一些唯一值并将其替换为参数。 These transformed arguments are then passed to the parameter template to check whether deduction succeeds or fails. 然后将这些转换后的参数传递给参数模板,以检查推导是成功还是失败。 As an example: 举个例子:

  • A1 is deduced against B1, which succeeds. A1是针对B1推断的,其成功。 ( int can be deduced from int ) int可以从int推导出来)
  • B1 is deduced against A1, ... as above. 如上所述,B1是针对A1,......推导出的。 Works fine. 工作正常。

Let's now look at the crucial deductions: 现在让我们来看看关键的推论:

  • B2 is deduced against A2, but as we used unique values for both Start and N , Start in template A is deduced inconsistently , which means that deduction fails here. B2是根据A2推导出来的, 但由于我们对StartN使用了唯一值,因此模板A中的Start不一致地推导出来 ,这意味着此处的推断失败。

  • A3 is deduced against B3, but since Coefficients is some unique type (not a specialization of IndexSequence !), deduction fails again. A3是根据B3推导出来的,但由于Coefficients是一些独特的类型(不是IndexSequence !的特化),因此扣除再次失败。

Deduction failed at least once in both directions: Thus no template is in its entirety more specialized than the other. 扣除在两个方向上至少失败一次:因此,没有一个模板完全比另一个更专业。


Solve this partial ordering ambiguity by eg writing the first specialization as 通过例如将第一个特化作为编写来解决这种部分排序歧义

template <int Start, int... As, int... Is>
struct Helper<Start, Start, IndexSequence<As...>, Is...> {
    using type = IndexSequence<Is...>;
};

Now, the second deduction that failed above doesn't fail anymore. 现在,上面失败的第二次扣除不再失败。 Only the one that took specialization B as the argument template. 只有将专业化B作为参数模板的那个。 That means that B is more specialized, and thus selected. 这意味着B更专业,因此被选中。

Demo . 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM