首页 > 编程笔记 > C++笔记 阅读:76

C++函数模板的重载

通义灵码
和普通函数一样,函数模板也可以重载。重载的函数模板,模板名称相同,但函数形参列表不同。

例如:
  1. template <typename Type>
  2. Type min(const Type*, int); // 注意第二个参数
  3.  
  4. template <typename Type>
  5. Type min(Type, Type); //两个参数类型相同
在上述定义中,两个模板的模板形参相同,都是一个类型(typename Type),模板名称也相同,都是 min。但函数形参列表不一样,一个是 (const Type *, int),另一个是(Type, Type),所以这两个函数模板是重载的。

同函数重载一样,函数模板的返回类型不作为重载的判断条件。

下面的主函数的定义说明了前面定义的两个模板如何使用:
  1. #include <cmath>
  2.  
  3. int main()
  4. {
  5. int ia[1024];
  6. int ival = min(ia, 1024); // Type == int; min(const int*, int)
  7. double dval = min(1.1, 2.2); // Type == double; min(double, double)
  8. return 0;
  9.  
  10. }
在上述主函数的定义中,第 6 行的第二个参数是一个整型数 1024,从定义上来讲,此处更适合第一个函数模板,所以该处的调用得到的模板实例就是第一个模板的实例。

如果存在多个候选的模板,那么在实参推演过程中,编译器倾向于选择那些函数实参跟形参类型相近的模板。例如在上面的例子中,实参 1024 是一个整型,而候选函数模板中,其中一个的形参也是整型,那么该模板就会被选来进行实例化。

尽管定义重载函数模板同定义重载函数一样简单,但二者也有不同。重载函数没有二义性的问题,而重载函数模板则可能导致二义性。

仍以上面的重载模板 min 为例,使其既可以支持类型参数相同的情况,也可以支持类型参数不同的情况:
  1. template <typename T>
  2. int min(T, T) { /* ...... */ } //两个参数类型相同的函数模板
  3.  
  4. template <typename T, typename U>
  5. int min(T, U); //两个参数类型不相同的函数模板
如果以如下的形式使用函数模板,将会导致二义性:
  • min(1024, 512);
因为在这个例子中,编译器无法决定到底该实例化哪个模板。第二个函数模板,虽然其模板参数声明为两个类型(T 和 U),但并没有限制这两个类型必须不同,所以语句“min(1024, 512);”也可以看做是调用第二个模板的实例。显然这样做会引起与第一个模板的冲突,从而导致编译错误。

但是,在这种情况下其实可以不必重载函数模板。因为所有能够匹配 min(T, T) 的调用,也完全可以匹配 min(T, U)。所以应该只提供 min(T, U) 的声明,而 min(T, T) 应该被删除。

在某些情况下,尽管可以采用重载函数模板,但在进行程序设计时,仍然应当尽量少地使用,以避免不小心带来的二义性。

实例演示函数模板重载

下面的例子展示了函数模板重载的一种应用:
  1. #include <iostream>
  2. #include <string>
  3.  
  4. // 基本模板
  5. template <typename T>
  6. void display(T value) {
  7. std::cout << "Basic template: " << value << std::endl;
  8. }
  9.  
  10. // 重载1:接受两个参数的版本
  11. template <typename T>
  12. void display(T value1, T value2) {
  13. std::cout << "Overloaded template with two parameters: " << value1 << ", " << value2 << std::endl;
  14. }
  15.  
  16. // 重载2:接受一个std::string和一个T类型的参数
  17. template <typename T>
  18. void display(std::string message, T value) {
  19. std::cout << message << ": " << value << std::endl;
  20. }
  21.  
  22. int main() {
  23. int a = 1;
  24. double b = 2.0;
  25. std::string str = "Hello";
  26.  
  27. // 使用基本模板
  28. display(a);
  29.  
  30. // 使用接受两个参数的重载版本
  31. display(a, a);
  32.  
  33. // 使用接受一个std::string和一个T类型的参数的重载版本
  34. display("Custom message", a);
  35.  
  36. return 0;
  37. }
输出结果为:

Basic template: 1
Overloaded template with two parameters: 1, 1
Custom message: 1

在这个例子中,display() 函数有以下几种不同的模板重载:
在 main() 函数中,我们对这些不同版本的 display() 函数进行了调用,以展示函数模板重载的工作方式。

相关文章