我有以下代码:
#include <iostream>
template <typename T>
void f (T) { std::cout << "f(T)" << std::endl; }
template <typename T>
void f (bool) { std::cout << "f(bool)" << std::endl; }
int main ( )
{
f(true); // #1 prints f(T)
f<bool>(true); // #2 prints f(bool)
}
该#1
线路的呼叫f(T)
,而#2
线路的呼叫f(bool)
。
为什么会这样?选择重载模板函数的规则是什么?
更新
我了解到,在第一次调用中,编译器T
在尝试调用第二个函数时无法推断,因此选择了第一个。
在第二个调用中,第二个功能被认为是在gcc上更好的匹配,而第一个功能是在VS2013下选择的。谁在这里做正确的事?顺便说一下,我仍然对该过程的完整描述感兴趣。
非专业功能模板也称为基础模板。基本模板可以是专门的。看看在不同情况下会调用哪个的重载规则非常简单,至少在较高级别上如此:
非模板功能是一等公民。与参数类型以及任何功能模板相匹配的普通旧非模板函数将在原本就很好的函数模板上进行选择。
如果没有一等公民可供选择,那么至少要和二等公民一样好,然后使用功能基础模板作为第二等公民的参考。根据一组相当合理的说法,选择哪个功能基础模板取决于哪个匹配最合适,并且是“最专业的”(重要说明:“专业化”的这种使用与模板专业化毫无关系;这只是一个不幸的口语化)奥术规则:
如果很明显有一个“最专业的”功能库模板,那么该模板就会被使用。如果该基本模板恰好专用于所使用的类型,则将使用该特殊化,否则将使用以正确类型实例化的基本模板。
否则(如您的情况),如果“最专业”的函数库模板有联系,则该调用是模棱两可的,因为编译器无法确定哪个更合适。程序员将必须做一些事情以限定调用并说出需要哪个。
否则,如果没有可以匹配的函数库模板,则调用是错误的,程序员将不得不修复代码。
如果要自定义函数基础模板,并希望该自定义参与重载解析(或在完全匹配的情况下始终使用),请使其成为普通的旧函数,而不是专门化的函数。并且,如果您确实提供了重载,请避免也提供专业化知识。
以上是从提取该职位通过的香草萨特和突出显示的子弹,你可以看到你的问题的根源
编辑
如果您尝试(不要这样做)在Visual Studio 2012中使用上述代码,则会得到
致命错误LNK1179:无效或损坏的文件:重复的COMDAT'?? $ f @ _N @@ YAX_N @ Z'
如此处所述,这是因为
您做了一些无效的C ++“欺骗”,它通过了编译器,但是您现在有了一个无效的* .obj,它使链接程序阻塞了。
而以下行应归咎于
f(true); // #1 prints f(T)
因此答案中的歧义没有保证的解决方案
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句