# 函数模板

URL: https://caijiao.org/cpp/stl/templates-func
Source: docs/cpp/stl/templates-func.md
Description: 本节介绍 C++ 中的函数模板，帮助理解其基本概念及应用，如何实现类型无关的函数。

C++ 中的函数模板允许创建与类型无关的函数，使得同一个函数能够处理不同的数据类型。函数模板是 C++ 提供的一个强大特性，它可以显著减少代码重复，提高代码的复用性和可维护性。

## 函数模板的基本语法

函数模板的定义通过 `template` 关键字开始，后面跟着一个或多个类型参数，函数模板的格式如下：

```cpp
template <typename T>
T function_name(T arg) {
    return arg;
}
````

* `template <typename T>`：定义了一个类型参数 `T`，`T` 可以是任意数据类型。
* `function_name`：函数的名称。
* `T arg`：参数类型是 `T`，表示接受任意类型的参数。
* `T`：返回类型也可以是 `T`，表示返回参数的类型。

### 示例

以下是一个简单的函数模板，计算两个参数的和：

```cpp
#include <iostream>
using namespace std;

// 函数模板
template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;           // 输出 7
    cout << add(3.5, 4.5) << endl;       // 输出 8.0
    cout << add('A', 1) << endl;         // 输出 'B'

    return 0;
}
```

在这个例子中，`add` 函数模板可以处理整数、浮点数和字符等不同类型的参数。编译器会根据调用时传入的参数类型自动推导模板类型。

## 多个类型参数

函数模板不仅可以使用单一类型参数，还可以使用多个类型参数。例如，我们可以定义一个接受两个不同类型参数的函数模板：

```cpp
template <typename T, typename U>
auto add(T a, U b) {
    return a + b;
}
```

### 示例：多个类型参数

```cpp
#include <iostream>
using namespace std;

template <typename T, typename U>
auto add(T a, U b) {
    return a + b;
}

int main() {
    cout << add(3, 4.5) << endl;   // 输出 7.5
    cout << add(2.3, 5) << endl;   // 输出 7.3

    return 0;
}
```

此处 `T` 和 `U` 分别是两个类型参数，C++ 编译器会根据传递的参数类型推导出相应的返回类型。

## 模板特化

有时我们需要为特定类型提供不同的实现，C++ 支持模板特化，即为某些特定类型定义特定的模板版本。

### 示例：特化一个类型

```cpp
#include <iostream>
using namespace std;

// 通用模板
template <typename T>
T add(T a, T b) {
    return a + b;
}

// 模板特化：针对 double 类型
template <>
double add(double a, double b) {
    cout << "Specialized template for double" << endl;
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;       // 输出 7
    cout << add(3.5, 4.5) << endl;   // 输出 Specialized template for double 8.0

    return 0;
}
```

在此例中，`add` 函数模板对 `double` 类型提供了一个特化版本，其他类型则使用通用版本。

## 默认模板参数

C++ 允许为模板提供默认参数，这样如果调用模板时未提供某个参数类型，编译器会使用默认类型。

### 示例：默认模板参数

```cpp
#include <iostream>
using namespace std;

template <typename T = int>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;      // 默认使用 int 类型，输出 7
    cout << add<double>(3.5, 4.5) << endl;  // 指定使用 double 类型，输出 8.0

    return 0;
}
```

在这个例子中，`T = int` 是 `T` 类型参数的默认值，调用 `add` 时如果没有指定类型，则默认为 `int`。

## 总结

函数模板是 C++ 中非常强大的一项功能，它允许编写与类型无关的函数，使代码更加通用和简洁。通过模板特化和默认模板参数等特性，可以灵活地根据不同的需求调整模板的行为。

* **模板函数**：通过 `template` 关键字定义，可以接受不同的数据类型。
* **多个类型参数**：可以定义接受多个不同类型的模板函数。
* **模板特化**：为特定类型提供特化版本。
* **默认模板参数**：为模板参数提供默认类型。

掌握函数模板的使用是编写高效、可扩展 C++ 代码的关键之一。
