为什么模板过载比简单转换更好?

时间:2015-03-29 01:51:20

标签: c++ templates overload-resolution

#include <iostream>
using namespace std;

template<typename T>
void func(T t)  { std::cout << "matched template\n"; }

void func(long x) { std::cout << "matched long\n"; }

int main()
{  
    func(0);
}

输出:

matched template

在其他情况下,当重载分辨率可能不明确时,非模板函数是首选,为什么这个不同?

3 个答案:

答案 0 :(得分:3)

§13.3.3[over.match.best] / p1-2:

  

1如下定义ICSi(F)

     
      
  • (1.1)[不适用的子弹省略]
  •   
  • (1.2)let ICSi(F)表示隐式转换序列,它将列表中的第i个参数转换为第i个参数的类型   可行的功能F。 13.3.3.1定义了隐式转换   序列和13.3.3.2定义了一个隐含的含义   转换序列是更好的转换序列或更糟   转换顺序比另一个。
  •   
     

鉴于这些定义,可行函数F1被定义为a   如果适用于所有参数,则比另一个可行函数F2具有更好的功能   iICSi(F1)转换序列不比ICSi(F2)差,   然后

     
      
  • (1.3)对于某些参数jICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果没有,

  •   
  • [省略了几个不适用的子弹]

  •   
  • (1.6)F1不是函数模板特化,F2是函数模板特化,或者,如果不是,
  •   
  • [不适用的子弹省略]
  •   
     

2如果只有一个可行的功能是更好的功能   比所有其他可行的功能,然后它是由选择的   超载分辨率;否则电话会形成不良。

§13.3.3.2[over.ics.rank],bullet 3.2:

  
      
  • (3.2)标准转换序列S1是比标准转换序列S2更好的转换序列   
        
    • (3.2.1)S1S2的正确子序列(比较13.3.3.1.1定义的规范形式的转换序列,不包括任何   左值变换;考虑身份转换序列   成为任何非身份转换序列的子序列)
    •   
  •   

让F1 = func<int>(int),F2 = func(long),只有一个类型为int的参数。所以ICS1(F1)是身份转换; ICS1(F2)是从intlong的整数转换;因此ICS1(F1)是一个比[{1}}每[over.ics.rank] /3.2.1更好的转换序列(因此根据定义并不比ICS1(F2)差)。因此,根据[over.match.best]中的子弹1.3,F1优于F2。在子弹1.6中,模板/非模板决胜局根本就没有发挥作用。

答案 1 :(得分:0)

我认为(但不是绝对肯定,即不知道标准的确切引用,尽管会试图找到)如果参数与非模板的类型完全不匹配,那么模板将启动。或者,换句话说,转换的数量往往会最小化。例如,

f(long)

vs

template <typename T>
f(T)

f(long)需要转换(从0,例如intlong),而模板不需要转换(当然)。

经过@ T.C.的一些挖掘和帮助后,标准的相关部分是Sec。 13.3.3,[over.match.best]。这是一个相当长的技术部分,但基本上说使用Identity转换的函数比非Identity转换更受欢迎。

答案 2 :(得分:0)

隐式转换可能带来开销,对程序员来说可能是意外的,因此我认为标准选择不涉及转换的选项是合乎逻辑的。