C++ Template 基础篇(一):函数模板

C++ Template 基础篇(一):函数模板
(2025–2026 年最实用、最清晰的入门讲解)

函数模板是 C++ 模板机制的入门级也是最常用的部分。
掌握函数模板后,你就能写出类型无关复用性极高的代码,这是现代 C++(尤其是泛型编程)的基石。

1. 什么是函数模板?

一句话定义

函数模板 = “写一次函数,让编译器根据调用时的参数类型自动生成多个具体版本的函数”

换句话说:你只写一份代码,编译器帮你生成 int 版、double 版、string 版、自定义类版…… 所有需要的版本。

2. 最经典的例子:求最大值

传统写法(重复劳动)

int max(int a, int b)          { return a > b ? a : b; }
double max(double a, double b) { return a > b ? a : b; }
long long max(long long a, long long b) { return a > b ? a : b; }
// …… 每种类型都要写一遍,太痛苦

用函数模板(一次编写,到处使用)

template <typename T>   // 或 template <class T>(两者等价)
T max(T a, T b) {
    return a > b ? a : b;
}

使用方式:

int main() {
    cout << max(3, 7)          << endl;     // 调用 int 版本
    cout << max(2.5, 1.8)      << endl;     // 调用 double 版本
    cout << max(100LL, 200LL)  << endl;     // 调用 long long 版本

    string s1 = "apple", s2 = "banana";
    cout << max(s1, s2)        << endl;     // 调用 string 版本(按字典序比较)
}

编译器在编译时会自动为每种调用生成一份具体函数(称为模板实例化)。

3. 模板语法核心关键词

写法含义现代推荐写法(C++11+)
template <typename T>T 是类型参数推荐(最清晰)
template <class T>与上面完全等价历史写法,仍合法
template <typename T1, typename T2>多个类型参数常见于 map、pair 等
template <int N>非类型参数(常量)后面会讲

4. 函数模板的推导规则(最容易出错的地方)

编译器如何决定 T 是什么?

规则总结(优先级从高到低):

  1. 显式指定类型(最强,强制使用)
max<double>(3, 4.5);     // 强制 T = double,3 会被隐式转换为 double
  1. 根据实参自动推导(最常见)
max(10, 20);        → T = int
max(1.2f, 3.4);     → T = float
  1. 常见陷阱:不同类型实参时推导失败
max(10, 3.14);      // 错误!编译器不知道 T 应该是 int 还是 double

解决办法(三种任选):

// 方案1:显式指定
max<double>(10, 3.14);

// 方案2:统一类型
max(10.0, 3.14);

// 方案3:重载或使用模板重载(后面会讲)

5. 模板函数的重载特化

模板函数也可以和普通函数、其他模板函数一起重载。

// 普通函数(优先级最高)
int max(int a, int b) {
    cout << "调用普通函数\n";
    return a > b ? a : b;
}

// 模板函数
template <typename T>
T max(T a, T b) {
    cout << "调用模板\n";
    return a > b ? a : b;
}

// 调用
max(5, 3);         // → 调用普通函数(非模板函数优先)
max(5.0, 3.0);     // → 调用模板(没有匹配的普通函数)

模板特化(针对特定类型写特殊版本)

// 针对 const char* 的特化版本(字符串比较用 strcmp)
template <>
const char* max<const char*>(const char* a, const char* b) {
    return strcmp(a, b) > 0 ? a : b;
}

6. 非类型模板参数(C++11 前就存在,很实用)

template <int N>
void print_fixed_size_array(int (&arr)[N]) {
    for (int i = 0; i < N; ++i) {
        cout << arr[i] << " ";
    }
}

int main() {
    int a[5] = {1,2,3,4,5};
    print_fixed_size_array(a);   // N 自动推导为 5
}

7. 2026 年写函数模板的现代最佳实践

// 推荐写法(C++20 概念 + auto 参数)
#include <concepts>

// 要求 T 支持 < 运算符
template <typename T>
    requires std::totally_ordered<T>   // C++20 概念约束
T my_max(T a, T b) {
    return a < b ? b : a;
}

// 更现代:C++20 缩写语法
auto my_max(std::totally_ordered auto a, std::totally_ordered auto b) {
    return a < b ? b : a;
}

8. 小结:函数模板一句话记住

函数模板让你写一份代码,编译器自动生成 N 份类型特化的函数。

核心口诀

  • template <typename T> 开头
  • T 代表“任意类型”
  • 编译器在调用时自动推导或显式指定 T
  • 重复参数类型自动去重,优先匹配普通函数
  • 想限制类型 → 用 C++20 概念(requires)

下一篇文章可以继续讲:

  • 类模板(class template)
  • 模板特化 & 偏特化
  • 变参模板(variadic template)
  • C++20 概念(concepts)实战

你想现在就继续看“类模板”还是先做几个函数模板练习题?或者有具体的使用场景(排序、比较、打印容器等)想看示例?告诉我,我立刻写给你。

文章已创建 4845

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部