C++模板函数重载决策

lis*_*rus 10 c++ templates overloading overload-resolution

我有以下代码:

#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)
}
Run Code Online (Sandbox Code Playgroud)

#1行称f(T),虽然#2行调用f(bool).

为什么会这样?选择重载模板函数的规则是什么?

UPDATE

我明白在第一次调用时,编译器T在尝试调用第二个函数时无法推断,因此选择第一个函数.

在第二个调用中,第二个函数被认为是更好的匹配gcc,而第一个函数是在VS2013下选择的.谁在这里做对了?顺便说一下,我仍然对这个过程的完整描述感兴趣.

Nik*_*iou 14

未特定的函数模板也称为底层基本模板.基本模板可以是专用的.在不同情况下查看哪些调用的重载规则非常简单,至少在高级别:

  • 非模板功能是一等公民.一个与参数类型以及任何函数模板匹配的普通旧的非模板函数将被选择在另外一样好的函数模板上.

  • 如果没有一流的公民可供选择至少同样好,那么接下来就咨询二级公民的功能基础模板.选择哪个功能基础模板取决于哪个匹配最好并且是"最专业的"(重要说明:这种"专用"的使用奇怪地与模板专业化无关;它只是一个不幸的口语)根据一组公平奥术规则:

    • 如果很明显有一个"最专业"的功能基础模板,那么就会使用它.如果该基本模板碰巧专门用于所使用的类型,则将使用特化,否则将使用使用正确类型实例化的基本模板.

    • 否则(如你的情况)如果"最专业"的函数库模板有一个平局,那么调用是不明确的,因为编译器无法确定哪个是更好的匹配.程序员必须做一些事情才能使电话有资格并说出想要的电话.

    • 否则,如果没有可以匹配的功能基础模板,则调用很糟糕,程序员必须修复代码.

如果要自定义函数库模板并希望该自定义参与重载解析(或者,在完全匹配的情况下始终使用),请将其设置为普通旧函数,而不是专门化.而且,如果您确实提供了重载,请避免提供专业化.

以上是从提取职位通过香草萨特和突出显示的子弹,你可以看到你的问题的根源

编辑

如果您使用Visual Studio 2012尝试(不要这样做)上面的代码,那么您将获得

致命错误LNK1179:文件无效或损坏:重复COMDAT'?? $ f @ _N @@ YAX_N @ Z'

正如这里所解释的那样,是因为

你做了一些无效C++的"技巧",并且它通过了编译器,但你现在有一个无效的*.obj,它会扼杀链接器.

以下几行应该归咎于

f(true);        // #1 prints f(T)
Run Code Online (Sandbox Code Playgroud)

所以答案中解释的歧义并没有得到保证