这是由this文章(第5页)
推动的template<class T>
T const &f(T const &a, T const &b){
return (a > b ? a : b);
}
template int const &f<int>(int const &, int const &);
int main(){
int x = 0, y = 0;
short s = 0;
f(x, y); // OK
f(x, s); // Is this call well-formed?
}
电话'f(x, s)'
是否格式良好?我假设由于功能模板'f'
已明确实例化,因此将应用标准转换,因此'short s'
将转换为'int'
以匹配对显式特化'f<int>'
的调用。但看起来这是不合理的?
标准的哪一部分讨论了此背景下适用的规则?
答案 0 :(得分:5)
不,呼叫f(x, s)
格式不正确。由于您没有明确说明要使用的特化,编译器使用参数推导来尝试实例化函数模板;此操作失败,因为x
和s
的类型不同,因此T
不明确。
适用的规则在13.3.1中的重载解析过程的规范中:
在候选者是函数模板的每种情况下,使用模板参数推导(14.8.3,14.8.2)生成候选函数模板特化。然后以通常的方式将这些候选人作为候选职能处理。
14.8.3 / 1也是相关的:
对于每个函数模板,如果参数推导和检查成功,则使用模板参数(推导和/或显式)来实例化单个函数模板特化,该特殊化被添加到候选函数集以用于重载解析。如果对于给定的函数模板,参数推导失败,则不会将该函数添加到该模板的候选函数集中。
函数模板是为T = int
显式实例化的,但编译器不知道它应该使用此实例化,直到它执行模板参数推断以确定T
应该是什么。
答案 1 :(得分:3)
调用f(x, s)
在语法上是格式良好的,但编译器将无法从中推导出模板参数T
,因为可能是int
或{{1} (因为第一个和第二个参数)。实例化模板没有帮助,只表示编译器编译该特化并将其添加到生成的目标文件中。
如果您希望自动将short
投射到s
,请使用int
。
答案 2 :(得分:1)
明确实例化的专业化没有任何更高的优先级或优先处理。从实例化的角度来看,它完全存在。对图书馆有用。
编译器根本无法确定要转换的参数,并且在没有额外声明的情况下就会卡住。
顺便说一句,如果你返回一个被转换的参数的引用,它将在临时到期时悬空。如果参数是对不同类型的引用,则无法正确形成返回值。
这是我更新的min
:
#include <type_traits>
template< typename A, typename B >
typename std::common_type< A, B >::type // cannot return ref
my_min( A const &a, B const &b ) {
return a < b? a : b;
}
// enable_if< is_same< A, B > > the old, return-by-reference impl
int main() {
int q = my_min( short(5), long(3) );
}