C++templates简单基础--Function Templates

C++的函数模板可以避免重复代码,提高代码复用。例如,通过模板定义的max函数可以适用于不同数据类型,但若类型不支持比较操作,则会导致编译错误。模板的实例化发生在使用时,且非模板函数在重载解析中优先级高于模板函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原来实现一个函数很容易,比如

int max (int a, int b)
{
    // 如果 a<b 就传回  b,否则传回  a
    return a < b ? b : a;
}

但现在a和b是double类型,上面的函数就不能用了,有几种方法解决,最简单的就是再写一个,如

double max (double a, double b)
{
    // 如果  a<b 就传回  b,否则传回  a
    return a < b ? b : a;   //这里暂时不考虑精度问题
}

那么问题来了,第2个函数是在做重复的事情,万一第1个函数有错误的话,之后不同类型的函数也会犯下相同的错误,
而且有可能不敢使用更复杂但更好的算法,因为这样会有更多的错误。
templates可以解决以上的问题,Templates如今已被大量运用。就拿C++标准库来说,几乎所有程序代码都以templates写成。
标 准库提供各式各样的功能:对objects和values排序的各种算法、管理各种元素的数据结构(容
器类别,container classes)、支持各种字符集的string(字符串)。

  • 定义Template

    以上max函数可以这样定义,

template <typename T>
inline T const& max (T const& a, T const& b)
{
    // 如果  a<b 就传回  b,否则传回  a
    return a < b ? b : a;
}

可以使用关键词 class 代替关键词 typename,就语意而言,前后两者毫无区别。

  • 使用Template

    定义了max函数,就可以使用了,

int main()
{
    int i = 42;
    std::cout << "max(7,i):  "<<::max(7,i)<<std::endl;
    double f1 = 3.4;
    double f2 = -6.7;
    std::cout << "max(f1,f2): "<< ::max(f1,f2) << std::endl;
    std::string s1 = "mathematics";
    std::string s2 = "math";
    std::cout << "max(s1,s2): "<< ::max(s1,s2) << std::endl;
}

程序对max()的三次调用都加了前缀字 “::”,以便确保被调用的是在全局命名空间 中定义的max()。
标准库内也有一个std::max() template,可能会在某些情 况下被调用,或在调用时引发模棱两可。
输出结果如下:

max(7,i): 42
max(f1,f2): 3.4
max(s1,s2): mathematics

这里有个问题,就是templates没有实例化,注意只要function template 被使用,就会自动引发实例化过程。
上面函数三次调用都成功了,三个类型都支持函数里的操作”<”,如果不支持就会编译错误

std::complex c1, c2; // 此类型并不提供 operator<

max(c1,c2); // 编译期出错

  • 自变量推导

    上面已经成功运用templates了,然后如果a和b的类型不一样呢

template <typename T>
inline T const& max(T const& a, T const& b);
...
max(4, 7);  // OK,两个T都被推导为int
max(4, 4.2);  // 错误:第一个T被推导为int,第二个T被推导为double

遇到这种情况,有3种方法解决

- 把两个自变量转型为相同类型:max(static_cast<double>(4), 4.2);

- 明确指定  T  的类型:max<double>(4, 4.2);

- 对各个  template parameters 使用不同的类型:template <typename T1, typename T2>
  • 重载

    最后,函数存在重载,当然function templates 也可以被重载

inline int const& max (int const& a, int const& b)
{
     return a < b ? b : a;
}
// 传回两任意类型的数值中的较大者
template <typename T>
inline T const& max (T const& a, T const& b)
{
     return a < b ? b : a;
}
// 传回三个任意类型值中的最大者
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
     return ::max (::max(a,b), c);
}
int main()
{
::max(7, 42, 68);  // 调用「接受三个自变量」的函数
::max(7.0, 42.0);  // 调用  max<double>(经由自变量推导)
::max('a', 'b');  // 调用  max<char>(经由自变量推导)
::max(7, 42);  // 调用「接受两个  int  自变量」的  non-template  函数
::max<>(7, 42);  // 调用  max<int>(经由自变量推导)
::max<double>(7, 42);  // 调用  max<double>(无需自变量推导)
::max('a', 42.7);  // 调用「接受两个  int  自变量」的  non-template  函数
}

上面例子说明non-template function可以和同名的function template共存,
当其它要素都相等时,重载解析机制会优先选择 non-template function,
而不选 择由 function template 实例化后的函数实体。
还有要把所有形式的重载函数写在 它们被调用之前,否则调用的函数选择可能不一样

template <typename T>
inline T const& max (T const& a, T const& b)
{
     return a < b ? b : a;
}
// 传回三个任意类型值的最大者
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
     return ::max (::max(a,b), c);
     // 即使自变量类型都是 int,这里也会调用  max()template。因为下面的函数定义来得太迟。
}
// 传回两个  ints 的较大者
inline int const& max (int const& a, int const& b)
{
     return a < b ? b : a;
}

本文的内容出自C++Templates 侯捷简体中文版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值