【发布时间】:2016-01-30 07:00:02
【问题描述】:
包含模板参数包的函数模板的部分排序独立于这些模板参数包的推导参数数量。
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
以上引自partial ordering of overload function templates。我不太明白为什么g(Tuple<int>()); // calls #3。具体来说,为什么不能调用#2?以下是我的推理,如有错误请指出:
注意:我会忽略#1 b/c 解释得很好here
第 1 步:推演、代换和重载解决方案提出了这些:
- void(Tuple
) [T1 = int, Types 为空] #2 - void(Tuple
) [T1 = int, Types& 为空] #3
第 2 步:转换两个函数模板:
- void g(Tuple);
- void g(Tuple
);
Step3:这是一个函数调用上下文,类型是函数调用有参数的那些函数参数类型:
- 从元组
推导出元组 OK [T1 = C2;类型... = Pack&...] - 从元组 推导出元组) 好吗? [T1 = C1;类型和...呢?可以从Pack1推导出来吗...?此处是否删除了参考?]
3) 如果P是引用类型,那么P所引用的类型用于推导。This好像没问题。
如果 P 具有包含模板参数列表
或 的形式之一,则该模板参数列表的每个元素 Pi 与其 A 的相应模板参数 Ai 匹配。如果最后一个 Pi 是一个包扩展,然后将其模式与 A 的模板参数列表中的每个剩余参数进行比较。没有以其他方式推导的尾随参数包被推导为一个空参数包。
Step4:如果最后一步正确。那么这意味着#3 并不比#2 更专业。所以对于应该解析到哪个函数模板是模棱两可的。
更新:我想我误解了上面的相关引述。当我们将 P 中的模板参数与 A 中的模板参数匹配时,它们会逐字匹配,这意味着当我们匹配时,对 函数调用 参数和参数所做的所有转换和分析都不会再次应用P/A 中的模板参数/参数(实际上是函数调用参数/参数)。然后它会在上面的步骤 3 中无法从Tuple< C1, Pack1...>) 推导出Tuple< T1, Types&...>。所以#3 更专业。
【问题讨论】:
-
您是否尝试过各种编译器的最新版本?
-
我只尝试过 g++。在哪里可以在线试用其他编译器?
标签: c++ templates overload-resolution