函数模板初探

函数模板初探,第1张

函数模板和函数的重载

仍然拿max函数举例。


使用double重载max函数。


然后分别使用floatdouble实例化:

template 
T max(T lhs,T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

double max(double lhs, double rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
  
    max(10.5f, 5.5f); // (1)
    max(10.5, 5.5);   // (2)
  
}

此时(1)和(2)分别会调用哪个函数?
答案是编译器会选择最匹配的函数。


  • (1):函数模板是更好的匹配,因为函数需要类型转换;
  • (2):函数模板和函数都可以匹配,在这种情况下,编译器会选择函数。


C++ Insights输出如下:

template 
T max(T lhs,T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
float max(float lhs, float rhs)
{
  return (lhs > rhs) ? lhs : rhs;
}
#endif


double max(double lhs, double rhs)
{
  return (lhs > rhs) ? lhs : rhs;
}


int main()
{
  max(10.5F, 5.5F);
  max(10.5, 5.5);
  return 0;
}
不同的模板参数

如果向max传递2个不同类型的参数:

template 
T max(T lhs,T rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
  
    max(10.5f, 5.5);
  
}

C++ Insights输出如下:

/home/insights/insights.cpp:8:5: error: no matching function for call to 'max'
    max(10.5f, 5.5);
    ^~~
/home/insights/insights.cpp:2:3: note: candidate template ignored: deduced conflicting types for parameter 'T' ('float' vs. 'double')
T max(T lhs,T rhs) {
  ^
1 error generated.
Error while processing /home/insights/insights.cpp.

编译器会报错,原因如下:

  • 如果可能的话,编译器将从函数参数推导模板参数;
  • 编译器会对每个函数模板参数进行推导;
  • 对于10.5f,编译器推导T为float;对于5.5,编译器推导T为double;
  • 显然,T不可能同时为float和double。


    所以编译器报错了。


解决这个问题也很简单,使用2个类型参数即可:

template 
??? max(T lhs,T2 rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
  
    max(10.5f, 5.5);
  
}

这个函数的返回值有可能是T,T2或从T/T2派生出来的类型,在C++11里面实现很简单。


有以下几种方式:

// automaticReturnTypeDeduction.cpp

#include 

template       // (1)
typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type max1(T1 lhs,T2 rhs) {
    return (lhs > rhs)? lhs : rhs;
}

template       // (2)
typename std::common_type::type max2(T1 lhs,T2 rhs) {
    return (lhs > rhs)? lhs : rhs;
}

template      // (3)
auto max3(T1 lhs,T2 rhs) {
    return (lhs > rhs)? lhs : rhs;
}

int main() {
  
    max1(10.5f, 5.5);                  
    max2(10.5f, 5.5);                  
    max3(10.5f, 5.5);                  
  
}
  • (1):typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type返回其中较大者;std::conditional是编译时的三元 *** 作符;
  • (2):typename std::common_type::type返回参数列表中类型的公共类型,其可以接受任意数量的参数;
  • (3):使用了auto的自动类型推导。


其中的typename是为了告诉编译器T1和T2是类型,当然,它们也可能是无类型或者模板。


C++ Insights主要输出如下:

  • (1)中较小类型float会被转换为double
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::conditional<(sizeof(float) > sizeof(double)), float, double>::type max1(float lhs, double rhs)
{
  return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif
  • (2)
/* First instantiated from: insights.cpp:10 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::common_type::type max2(float lhs, double rhs)
{
  return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif
  • (3)
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double max3(float lhs, double rhs)
{
  return (static_cast(lhs) > rhs) ? static_cast(lhs) : rhs;
}
#endif

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/562725.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)

保存