为什么下面的重载分辨率调用非模板函数?

时间:2013-03-23 12:01:20

标签: c++ templates overloading

为什么以下表达式max(x, y)中的调用return max(max(x, y), z);的重载解析会导致调用非模板函数char const* max(char const*, char const*)

据我所知,函数max<const char*>(x, y)比前者更合适,因为xconst char* const&yconst char* const& }!

#include <iostream>

template <typename T>
T const& max (T const& x, T const& y)
{
    return x < y ? y : x;
}

char const* max (char const* x, char const* y)
{
    return std::strcmp(x, y) < 0 ? y : x;
}

template <typename T>
T const& max (T const& x, T const& y, T const& z)
{
    return max (max(x, y), z);
}

int main ()
{
    const char* sx = "String_x";
    const char* sy = "String_y";
    const char* sz = "String_z";
    max(sx, sy, sz);
}

2 个答案:

答案 0 :(得分:4)

  

为什么以下表达式max(x, y)中的调用return max(max(x, y), z);的重载解析会导致调用非模板函数char const* max(char const*, char const*)

调用此函数时:

template <typename T>
T const& max (T const& x, T const& y, T const& z)
{
    return max (max(x, y), z);
}

T推断为const char*。因此,此签名被实例化:

const char* const& max (
    const char* const& x, 
    const char* const& y, 
    const char* const& z
    )

该函数在内部调用max()的二进制版本,其参数类型为const char*。模板和非模板重载都适用于const char*类型的参数。

但是,当两个函数可用于解析调用时,其中一个不是模板,非模板版本被认为是最合适的

根据C ++ 11标准的第13.3.3 / 1段:

  

鉴于这些定义,**可行函数F1被定义为比另一个可行函数更好的函数   F2如果**对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,然后

     

- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,

     

- 上下文是用户定义转换的初始化(见8.5,13.3.1.5和13.3.1.6)和   从返回类型F1到目标类型的标准转换序列(即,类型的   正在初始化的实体)是比标准转换序列更好的转换序列   F2的返回类型到目标类型。 [...]或者,如果不是那样,

     

- F1是非模板功能,F2是功能模板专业化,或者,如果不是,

     

- F1和F2是功能模板专精,F1的功能模板更专业   根据14.5.6.2中描述的偏序规则,比F2的模板。

这解释了为什么选择非模板重载。

答案 1 :(得分:0)

Argument Matching - 为当前范围内的函数声明的最佳匹配选择了重载函数。

  

如果模板参数推断成功,则生成函数   与其他函数进行比较以确定最佳匹配,   遵循重载决策的规则

  
      
  • 找到了完全匹配。

  •   
  • 进行了一次微不足道的转换。

  •   
  • 进行了整体推广。

  •   
  • 存在标准转换为所需的参数类型。

  •   
  • 存在用户定义的转换(转换运算符或构造函数)到所需的参数类型。

  •   
  • 找到省略号代表的参数。

  •