【问题标题】:Function Template Type Deduction Rules函数模板类型推演规则
【发布时间】:2022-01-05 13:16:02
【问题描述】:

我有:

template<typename ...Ts, typename U, typename=void>
void valid(Ts..., U){}

int main() {
    valid(1.0, 1, 2, 3);
}

clang 抱怨:

note: candidate function [with Ts = <>, U = double, $2 = void] not viable: requires 1 argument, but 4 were provided
void valid(Ts..., U){}
     ^

而 gcc 抱怨:

<source>:2:6: note:   template argument deduction/substitution failed:
<source>:5:10: note:   candidate expects 1 argument, 4 provided
    5 |     valid(1.0, 1, 2, 3);
      |     ~~~~~^~~~~~~~~~~~~~

根据 cling,编译器似乎推断出 Tn 是一个空包(即 )。这是为什么?我认为给定参数列表 (1.0, 1, 2, 3),U 将推导出为 intTn... 将是 double, int, int。这里类型推导的规则是什么?

如果我将调用者更改为:

valid<double, int, int>(1.0, 1, 2, 3);

它有效。但是,如果我将其更改为:

valid<double, int, int, int>(1.0, 1, 2, 3);

失败了:

<source>:2:6: note:   template argument deduction/substitution failed:
<source>:5:33: note:   candidate expects 5 arguments, 4 provided
    5 |     valid<double, int, int, int>(1.0, 1, 2, 3);
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~

这里使用什么规则来确定我可以在类型参数列表中指定哪些类型?

谢谢。

【问题讨论】:

  • Ts... 是非扣除上下文,因此模板参数扣除永远不会为它工作。尚不确定为什么明确指定的参数不起作用。 "[temp.deduct.type]/5 非推导上下文是: ... (5.7) — 一个函数参数包,不会出现在参数声明列表。”
  • 啊。 "[temp.deduct.type]/9 ...如果Pi是包展开,则Pi的模式与A 的模板参数列表中的每个剩余参数。每个比较推导出模板参数包中由 Pi 扩展的后续位置的模板参数。”强调我的。换句话说,一旦您开始匹配参数包,所有后续参数都被假定属于该参数包。所以在valid&lt;double, int, int, int&gt;(1.0, 1, 2, 3)调用中,Ts...被取为四种类型{double, int, int, int},然后实例化需要5个参数。

标签: c++11 variadic-templates


【解决方案1】:

首先,为什么没有显式指定模板参数时模板参数推导失败,如valid(1.0, 1, 2, 3)。这很简单——一个没有尾随的参数包(不是函数参数列表中的最后一个)是非推导上下文:

[temp.deduct.type]/5 非推断上下文是:
...
(5.7) — 一个函数参数包,不会出现在 parameter-declaration-list 的末尾。


其次,在存在参数包的情况下,如何明确指定模板参数与模板参数匹配。它的工作方式是,一旦你得到一个对应于包的参数,所有后续参数都将被视为该包的一部分。

[temp.deduct.type]/9 ... 如果 Pi 是一个包展开,那么 的模式>PiA 的模板参数列表中的每个剩余参数进行比较。每次比较都会推导出模板参数包中后续位置的模板参数,这些模板参数包由 Pi 扩展。

因此,valid&lt;double, int, int&gt;(1.0, 1, 2, 3) 有效,因为Ts... 被视为三种类型{double, int, int},并且U 是从第四个参数3 推导出来的。 valid&lt;double, int, int, int&gt;(1.0, 1, 2, 3) 不起作用,因为Ts... 被认为是{double, int, int, int} 的四种类型,然后U 类型的最后一个参数没有函数参数。

【讨论】:

  • 谢谢。现在我得到了“非推断上下文”部分。对于明确指定的模板参数一,我不太了解标准中的措辞。由于Pi 是一个包扩展(在我的示例中:double, int, intdouble, int, int, int),那么Pi 真的是“比较”的吗?看不出比较是什么......
  • Piith 模板参数,这里是Ts...A 是模板参数列表,这里是&lt;double, int, int, int&gt;
猜你喜欢
  • 2014-04-17
  • 1970-01-01
  • 2014-07-26
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多