← 返回首页

C++ 模板详解

1. 函数模板基础

template<typename T>
T max(T a, T b) {
    return b < a ? a : b;
}

由于历史原因,除了 typename 之外你还可以使用 class 来定义类型参数。应该优先使用 typename。

在编译阶段,模板并不是被编译成一个可以支持多种类型的实体。而是对每一个用于该模板的类型都会产生一个独立的实体。这个过程叫做实例化

2. 两阶段编译检查(Two-Phase Translation)

模板分两步编译:

  1. 模板定义阶段:检查不依赖于类型参数的部分
    • 语法检查(如缺少分号)
    • 未定义的不依赖模板参数的名称
    • 未使用模板参数的 static assertions
  2. 模板实例化阶段:检查依赖类型参数的部分,确保所有代码有效

3. 模板参数推断

模板参数由被传递的调用参数决定。

类型推断中的类型转换

默认调用参数

类型推断不适用于默认调用参数:

template<typename T>
void f(T = "");  

f(1);   // OK: T 推断为 int
f();    // ERROR: 无法推断 T 的类型

// 需要同时给模板参数默认值
template<typename T = std::string>
void f(T = "");
f();    // OK

4. 返回类型推断

C++14 起可以使用 auto 推导返回类型:

template<typename T1, typename T2>
auto max(T1 a, T2 b) {
    return b < a ? a : b;
}

C++11 中可以使用尾置返回类型:

template<typename T1, typename T2>
auto max(T1 a, T2 b) -> decltype(b<a?a:b) {
    return b < a ? a : b;
}

5. 公共类型(Common Type)

C++11 提供 std::common_type 来指定"更一般类型":

#include <type_traits>

template<typename T1, typename T2>
std::common_type_t<T1,T2> max(T1 a, T2 b) {
    return b < a ? a : b;
}