函数模板

Why function templates

The definitions of some overloaded functions may be similar.
函数重载的定义可能相似。

  1. int sum(int x, int y)
  2. {
  3. cout << "sum(int, int) is called" << endl;
  4. return x + y;
  5. }
  6. float sum(float x, float y)
  7. {
  8. cout << "sum(float, float) is called" << endl;
  9. return x + y;
  10. }
  11. double sum(double x, double y)
  12. {
  13. cout << "sum(double, double) is called" << endl;
  14. return x + y;
  15. }

三个函数的功能相同,计算逻辑相同,只是类型不同。这三个函数功能非常简单,无非就是两数相加,但是如果函数功能非常复杂,也仅仅是函数返回类型不同,这三个函数就会有非常多重复的地方,代码不美观又冗余,维护困难,怎么办?

Explicit instantiation

  • A function template is not a type, or a function, or any other entity.
  • No code is generated from a source file that contains only template definitions.
  • The template arguments must be determined, then the compiler can generate an actual function ```cpp

    include

    include

    using namespace std;

template T sum(T x, T y) { cout << “The input type is “ << typeid(T).name() << endl; return x + y; } // Explicitly instantiate template double sum(double, double);

// instantiates sum(char, char), template argument deduced template char sum<>(char, char);

// instantiates sum(int, int), template argument deduced template int sum(int, int);

int main() { auto val = sum(4.1, 5.2); cout << val << endl;

  1. auto val_1 = sum(4, 5);
  2. cout << val_1 << endl;
  3. auto val_2 = sum('2', '1');
  4. cout << val_2 << endl;
  5. return 0;

}

// The input type is d // 9.3 // The input type is i // 9 // The input type is c // c

`T`是泛型,通用数据类型,可以代表各种数据类型。`typeid(T).name() `:输入参数的类型。<br />这就是一个函数模板,编译器编译的时候,遇到函数模板,并不会生成可执行代码,因为编译器不知道加法(整数加法与浮点数加法是不同的)怎么执行。

如果想让编译器编译它,需要再**实例化**这个模板函数,告诉编译器`T`是`double`类型,然后编译器就会生成三个不同的函数,其在机器指令中是不同的代码,调用它们的机器码的地址也是不同的。

函数模板是虚拟的,编译器把握不住,所以编译器一定要要求生成一个实实在在的函数,所以函数模板需要实例化,才能生成真正的函数。

尝试:<br />将第一个实例化的`double`类型改成`float`,运行结果:`The input type is d`;将其注释掉,仍然可以编译通过,运行结果仍然是:`The input type is d`;<br />WHY????

函数模板可以做显式的实例化,也可以做隐式的实例化!

**Implicit instantiation**<br />Implicit instantiation occurs when a function template is not `explicitly instantiated`.<br />编译器在编译的时候,遇到函数模板,但不知道如何实现该模板函数,就会去找显式的声明,显式实例化找不到,就会去找函数调用,就会隐式的实例化该模板函数,生成函数实现的机器码
```cpp
#include <iostream>
#include <typeinfo>
using namespace std;

template<typename T>
T sum(T x, T y)
{
    cout << "The input type is " << typeid(T).name() << endl;
    return x + y;
}

int main()
{
    // Implicitly instantiates product<int>(int, int)
    cout << "sum = " << sum<int>(2.2f, 3.0f) << endl;
    // Implicitly instantiates product<float>(float, float)
    cout << "sum = " << sum(2.2f, 3.0f) << endl;

    return 0;
}

// sum = The input type is i
// 5
// sum = The input type is f
// 5.2

Function template specialization

We have a function template: template<typename T> T sum(T x, T y)

  • If the input type is Point
    struct Point
    {
      int x; 
      int y;
    };
    
    But no + operator for Point
    We need to give a special definition for this case. ```cpp

    include

    include

    using namespace std;

template T sum(T x, T y) { cout << “The input type is “ << typeid(T).name() << endl; return x + y; }

struct Point { int x; int y; };

// Specialization for Point + Point operation template<> // <> 特例化 Point sum(Point pt1, Point pt2) { cout << “The input type is “ << typeid(pt1).name() << endl; Point pt; pt.x = pt1.x + pt2.x; pt.y = pt1.y + pt2.y; return pt; }

int main() { //Explicit instantiated functions cout << “sum = “ << sum(1, 2) << endl; cout << “sum = “ << sum(1.1, 2.2) << endl;

Point pt1 {1, 2};
Point pt2 {2, 3};
Point pt = sum(pt1, pt2);
cout << "pt = (" << pt.x << ", " << pt.y << ")" << endl;
return 0;

} ```