如何解决这种歧义?

钥匙

在下面的代码中:

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

对于自变量模板的每个自变量,将为每个模板参数组成一些唯一值,并将其替换为自变量。然后,将这些转换后的参数传递到参数模板,以检查推导是成功还是失败。举个例子:

  • 将A1推导为B1,则B1成功。int可以从推导得出int
  • 如上所述,针对A1 ...推导出B1。工作正常。

现在让我们看一下关键的推论:

  • 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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何解决这种歧义?

来自分类Dev

如何解决钻石问题的这种歧义

来自分类Dev

如何解决通用扩展方法中的这种歧义?

来自分类Dev

如何解决我的GADT中的歧义

来自分类Dev

如何解决cucumberjs中的歧义问题?

来自分类Dev

如何解决这种循环依赖关系?

来自分类Dev

如何解决这种复发关系?

来自分类Dev

如何解决这种奇怪的DataGridview行为

来自分类Dev

如何解决这种循环依赖?

来自分类Dev

哈希表如何解决存储桶的歧义和探测?

来自分类Dev

在while循环中添加中断如何解决过载歧义?

来自分类Dev

如何解决方法引用中的重载歧义?

来自分类Dev

如何解决对重载定义的歧义引用

来自分类Dev

如何解决Swift中的歧义类型错误?

来自分类Dev

如何解决Qt插槽中功能的歧义

来自分类Dev

如何解决传递给Boost线程的函数中的歧义

来自分类Dev

如何解决“ fpclassify”:对重载函数的歧义调用

来自分类Dev

引用如何解决多重继承中的歧义?

来自分类Dev

如何解决以下代码中的函数重载歧义

来自分类Dev

如何解决歧义和冲突LR解析器?

来自分类Dev

如何解决JavaFX TableView中的这种视觉故障?

来自分类Dev

如何解决这种语法中的移位减少冲突

来自分类Dev

如何解决EF中的这种循环依赖

来自分类Dev

这种方法如何解决我的阶乘?

来自分类Dev

在这种情况下如何解决NoMethodError?

来自分类Dev

我该如何解决SwipeRefreshLayout的这种不良行为

来自分类Dev

如何解决EF中的这种循环依赖

来自分类Dev

如何解决这种从角度到laravel的发布?

来自分类Dev

如何解决这种触发递归思维的打击?