【发布时间】:2015-10-29 23:19:40
【问题描述】:
具体来说,
template<class...> struct Tuple { };
template< class... Types> void g(Tuple<Types ...>); // #1
// template<class T1, class... Types> void g(Tuple<T1, Types ...>); // #2
template<class T1, class... Types> void g(Tuple<T1, Types& ...>); // #3
g(Tuple<>()); // calls #1
g(Tuple<int, float>()); // calls #2
g(Tuple<int, float&>()); // calls #3
g(Tuple<int>()); // calls #3
如果 #2 未注释,g() 将按照 cmets 中的说明进行解析。让我吃惊的是,如果我注释掉#2 行,g() 的调用会这样解决:
g(Tuple<>()); // calls #1
g(Tuple<int, float>()); // calls **#1 ???? why not #3????**
g(Tuple<int, float&>()); // calls #3
g(Tuple<int>()); // calls #3
从下面的示例和解释中,我看不出为什么g(Tuple<int, float>()); 无法解析为#3。是以下两条规则的方向应用:
如果参数包作为最后一个 P 出现,则类型 P 与调用的每个剩余参数的类型 A 匹配。每个匹配都会推导出包扩展中下一个位置的模板参数。
template<class ... Types> void f(Types& ...);
void h(int x, float& y) {
const int z = x;
f(x, y, z); // P=Types&..., A1=x: deduces the first member of Types... to int
// P=Types&..., A2=y: deduces the second member of Types... to float
// P=Types&..., A3=z: deduces the third member of Types... to const int
// calls f<int, float, const int>
如果 P 具有包含模板参数列表
<T>或<I>的形式之一,则该模板参数列表的每个元素 Pi 与其 A 的相应模板参数 Ai 匹配。如果最后一个 Pi 是一个包扩展,然后将其模式与 A 的模板参数列表中的每个剩余参数进行比较。没有以其他方式推导的尾随参数包被推导为一个空参数包。
【问题讨论】:
-
如果目标类型之一不是引用 (
float),您如何在Types&...中推断出Types? -
没有
Types...的值会使Types&...等于float。 -
@aschepler 我希望规则就这么简单。但是当 P 是
的形式时,它就像我引用的那样被分解。所以最终被扣除的是以下对 (T1/int) 和 (Types&.../float)。作为我引用的示例代码,可以使用 P=Types&... 和 A= float:结果是 Pack Types... 的第一个成员只是 float -
@Columbo 如果您说的是正确的,示例代码 f(x,y,z) 是如何工作的?函数参数都是引用,但 x、y 和 z 都不是引用。
-
@aschepler @ Columbo 你们也可以对相关问题发表评论吗*.com/q/33426038/1021388?
标签: c++ templates overload-resolution