函数模板
用 template <typename T> 参数化类型,编译器按实参推导 T,生成对应实例。一次定义,多种类型复用。
template <typename T>
T max(T a, T b) { return a > b ? a : b; }
int x = max(3, 5); // T 推导为 int
double y = max(1.2, 3.4); // T 推导为 double模板在编译期生成专用代码,运行期无类型擦除开销,是 C++ 零成本抽象的典型代表。
类模板
类也能参数化,如 std::vector<T>。成员定义在类内时随类一起模板化。
template <typename T>
class Box {
T value_;
public:
Box(T v) : value_(v) {}
T get() const { return value_; }
};
Box<int> b(42);模板特化
为特定类型提供定制实现:全特化(指定全部参数)、偏特化(部分参数)。常用于优化或特殊行为。
template <typename T>
struct traits { static constexpr bool is_ptr = false; };
template <typename T>
struct traits<T*> { static constexpr bool is_ptr = true; }; // 偏特化concepts 约束
C++20 的 concepts 给模板参数加语义约束,错误在调用处清晰报出,取代晦涩的 SFINAE。requires 表达约束。
#include <concepts>
template <std::integral T> // 约束 T 为整数类型
T add(T a, T b) { return a + b; }
// add(1.0, 2.0); // 编译错误:不满足 integral新代码用 concepts 代替 SFINAE 技巧,错误信息可读、意图清晰,且能作为函数重载的区分依据。
类型萃取
通过 type_traits 在编译期查询/变换类型(is_same、remove_reference、decay),配合 enable_if/concept 做条件实现。
#include <type_traits>
static_assert(std::is_integral_v<int>);
static_assert(!std::is_pointer_v<int>);constexpr
constexpr 让函数在编译期求值(若参数均为编译期常量),把计算从运行期搬到编译期,零运行时成本。
constexpr int square(int n) { return n * n; }
constexpr int s = square(8); // 编译期算出 64C++20 consteval 强制编译期;if constexpr 在编译期按条件丢弃分支,常用于模板里的类型分发。
变参模板
变参模板接受任意数量模板/函数参数,常用递归展开或折叠表达式(C++17)处理。
template <typename... Ts>
auto sum(Ts... xs) { return (xs + ...); } // 折叠表达式
int s = sum(1, 2, 3, 4); // 10常见陷阱与 FAQ
老代码的 SFINAE 错误极晦涩。改用 concepts 约束参数,错误会精确指向"不满足某概念",大幅提升可读性。
模板通常需在使用处实例化,所以定义多放在头文件(或用 .inl / 显式实例化)。否则链接期找不到实例化代码。
不必。constexpr 函数也能在运行期调用;只要结果用于编译期上下文(如数组大小、static_assert)且参数恒定,才在编译期求值。