1. 模板基础与编译原理
模板的编译过程
cpp
复制代码
// 模板定义(通常在头文件中)
template<typename T>
class Vector {
private:
T* data_;
size_t size_;
public:
Vector(size_t size) : size_(size), data_(new T[size]) {}
~Vector() { delete[] data_; }
T& operatorsize_t index { return data_[index]; }
const T& operatorsize_t index const { return data_[index]; }
};
// 模板实例化(编译器在编译时生成具体代码)
Vector<int> int_vec(10); // 实例化 Vector<int>
Vector<double> double_vec(5); // 实例化 Vector<double>
两阶段编译机制
cpp
复制代码
template<typename T>
void process(T value) {
value.non_existent_method(); // 第一阶段:语法检查通过
// 第二阶段:实例化时才会报错
}
int main() {
process(42); // 编译错误:int没有non_existent_method方法
}
2. 函数模板深度解析
模板参数推导机制
cpp
复制代码
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
// 推导示例
max(1, 2); // T = int
max(1.0, 2.0); // T = double
max<int>(1, 2.5); // 显式指定T=int,2.5被转换为int
// 复杂的类型推导
template<typename T>
void f(T param) {}
int x = 42;
const int cx = x;
const int& rx = x;
f(x); // T = int, param = int
f(cx); // T = int, param = int(const被忽略)
f(rx); // T = int, param = int(引用和const被忽略)
完美转发与引用折叠
cpp
复制代码
template<typename T>
void forward_value(T&& arg) { // 万能引用
process_value(std::forward<T>(arg)); // 完美转发
}
// 引用折叠规则:
// T& & -> T&
// T& && -> T&
// T&& & -> T&
// T&& && -> T&&
int x = 42;
forward_value(x); // T = int&, arg = int&
forward_value(std::move(x));// T = int, arg = int&&
forward_value(100); // T = int, arg = int&&
SFINAE(替换失败不是错误)
cpp
复制代码
// 检测类型是否有serialize方法
template<typename T>
class has_serialize {
private:
template<typename U>
static auto test(int) -> decltype(std::declval<U>().serialize(), std::true_type{});
template<typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
// 应用:根据特性选择实现
template<typename T>
std::enable_if_t<has_serialize<T>::value, std::string>
serialize(const T& obj) {
return obj.serialize(); // 使用成员方法
}
template<typename T>
std::enable_if_t<!has_serialize<T>::value, std::string>
serialize(const T& obj) {
return std::to_string(obj); // 使用通用转换
}
3. 类模板高级特性
模板特化与偏特化
cpp
复制代码
// 主模板
template<typename T>
class TypeInfo {
public:
static const char* name() { return "unknown"; }
};
// 全特化
template<>
class TypeInfo<int> {
public:
static const char* name() { return "int"; }
};
// 偏特化(指针类型)
template<typename T>
class TypeInfo<T*> {
public:
static const char* name() { return "pointer"; }
};
// 偏特化(引用类型)
template<typename T>
class TypeInfo<T&> {
public:
static const char* name() { return "reference"; }
};
可变参数模板
cpp
复制代码
// 递归展开
template<typename T>
void print(T value) {
std::cout << value << std::endl;
}
template<typename T, typename... Args>
void print(T value, Args... args) {
std::cout << value << ", ";
print(args...); // 递归调用
}
// 折叠表达式(C++17)
template<typename... Args>
auto sum(Args... args) {
return (args + ...); // 折叠表达式
}
// 完美转发的可变参数
template<typename... Args>
void emplace_back(Args&&... args) {
// 使用完美转发构造对象
new (storage) T(std::forward<Args>(args)...);
}
模板元编程
cpp
复制代码
// 编译时计算斐波那契数列
template<int N>
struct Fibonacci {
static constexpr int value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};
template<>
struct Fibonacci<0> {
static constexpr int value = 0;
};
template<>
struct Fibonacci<1> {
static constexpr int value = 1;
};
// 使用
constexpr int fib10 = Fibonacci<10>::value; // 编译时计算
// 类型列表操作
template<typename... Types>
class TypeList {};
template<typename List>
class Front;
template<typename Head, typename... Tail>
class Front<TypeList<Head, Tail...>> {
public:
using type = Head;
};
using MyList = TypeList<int, double, std::string>;
using FirstType = Front<MyList>::type; // int
4. 模板设计模式与技巧
CRTP(奇异递归模板模式)
cpp
复制代码
// 静态多态
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
static void static_interface() {
Derived::static_implementation();
}
};
class Derived1 : public Base<Derived1> {
public:
void implementation() {
std::cout << "Derived1 implementation\n";
}
static void static_implementation() {
std::cout << "Derived1 static implementation\n";
}
};
// 应用:对象计数
template<typename T>
class ObjectCounter {
private:
inline static int count_ = 0;
protected:
ObjectCounter() { ++count_; }
ObjectCounter(const ObjectCounter&) { ++count_; }
ObjectCounter(ObjectCounter&&) { ++count_; }
~ObjectCounter() { --count_; }
public:
static int alive() { return count_; }
};
class MyClass : public ObjectCounter<MyClass> {
// 自动获得对象计数功能
};
策略模式与模板
cpp
复制代码
// 排序策略
template<typename T>
struct QuickSort {
void sort(std::vector<T>& data) {
std::sort(data.begin(), data.end());
}
};
template<typename T>
struct MergeSort {
void sort(std::vector<T>& data) {
// 实现归并排序
}
};
// 使用策略的容器
template<typename T, typename SortStrategy = QuickSort<T>>
class SortedContainer {
private:
std::vector<T> data_;
SortStrategy sorter_;
public:
void add(const T& value) {
data_.push_back(value);
sorter_.sort(data_);
}
};
// 使用
SortedContainer<int, QuickSort<int>> quick_container;
SortedContainer<int, MergeSort<int>> merge_container;
类型萃取(Type Traits)
cpp
复制代码
// 自定义类型萃取
template<typename T>
struct is_pointer : std::false_type {};
template<typename T>
struct is_pointer<T*> : std::true_type {};
template<typename T>
struct is_numeric {
static constexpr bool value =
std::is_integral_v<T> || std::is_floating_point_v<T>;
};
// 应用:根据类型选择算法
template<typename T>
void process(T value) {
if constexpr (is_numeric<T>::value) {
// 数值类型的优化处理
std::cout << "Numeric: " << value * 2 << std::endl;
} else if constexpr (std::is_pointer_v<T>) {
// 指针类型的特殊处理
std::cout << "Pointer: " << *value << std::endl;
} else {
// 通用处理
std::cout << "Generic: " << value << std::endl;
}
}
5. 模板性能优化
编译期优化技术
cpp
复制代码
// 编译期字符串处理
template<size_t N>
struct FixedString {
char data[N] = {};
constexpr FixedString(const char (&str)[N]) {
std::copy_n(str, N, data);
}
constexpr bool operator==(const FixedString& other) const {
return std::equal(data, data + N, other.data);
}
};
// 编译期哈希
template<FixedString Str>
constexpr size_t hash() {
size_t result = 0;
for (size_t i = 0; i < sizeof(Str.data); ++i) {
result = (result * 131) + Str.data[i];
}
return result;
}
// 使用
constexpr auto str = FixedString("hello");
constexpr size_t h = hash<str>(); // 编译期计算
内联与优化
cpp
复制代码
// 小函数模板通常会被内联
template<typename T>
T square(T x) { // 很可能被内联
return x * x;
}
// 避免模板代码膨胀
template<typename T>
class Pimpl {
private:
struct Implementation; // 前向声明
std::unique_ptr<Implementation> pimpl_; // 隐藏实现细节
public:
// 接口函数,不依赖具体类型
void do_something();
};
// 显式实例化减少编译时间
// 在头文件中声明
template<typename T>
class ExpensiveTemplate {
// 复杂的模板实现
};
// 在源文件中显式实例化
template class ExpensiveTemplate<int>;
template class ExpensiveTemplate<double>;
6. 现代C++模板特性
C++17 特性
cpp
复制代码
// 类模板参数推导
std::pair p(1, 2.0); // 推导为 std::pair<int, double>
std::vector v{1, 2, 3}; // 推导为 std::vector<int>
// if constexpr
template<typename T>
auto get_value(T t) {
if constexpr (std::is_pointer_v<T>) {
return *t;
} else {
return t;
}
}
// 折叠表达式
template<typename... Args>
bool all_true(Args... args) {
return (args && ...); // 逻辑与折叠
}
C++20 概念(Concepts)
cpp
复制代码
// 定义概念
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
};
// 使用概念约束模板
template<Numeric T>
T square(T x) {
return x * x;
}
template<typename T> requires Addable<T>
T add(T a, T b) {
return a + b;
}
// 简写语法
auto add(Addable auto a, Addable auto b) {
return a + b;
}
7. 模板调试与错误处理
静态断言
cpp
复制代码
template<typename T>
class Vector {
static_assert(std::is_default_constructible_v<T>,
"T must be default constructible");
public:
// 实现...
};
// 自定义错误消息
template<typename From, typename To>
void convert(const From& from, To& to) {
static_assert(std::is_convertible_v<From, To>,
"Cannot convert between these types");
to = static_cast<To>(from);
}
编译时调试
cpp
复制代码
// 类型打印工具
template<typename T>
void print_type() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
// 使用
print_type<std::vector<int>>();
// 输出:void print_type() [T = std::vector<int>]
// 概念检查工具
template<typename T>
concept Checkable = requires {
requires sizeof(T) > 4;
requires std::is_copy_constructible_v<T>;
};
static_assert(Checkable<int>); // 编译时检查
8. 最佳实践总结
模板设计原则
cpp
复制代码
// 1. 优先使用函数对象而非函数指针
template<typename Func>
void execute(Func func) { // 更好的内联机会
func();
}
// 2. 提供完整的类型约束
template<typename T> requires std::copyable<T>
class Container {
// 明确要求T可拷贝
};
// 3. 使用SFINAE友好技术
template<typename T>
auto begin(T& container) -> decltype(container.begin()) {
return container.begin();
}
template<typename T, size_t N>
T* begin(T (&array)[N]) {
return array;
}
// 4. 避免过度泛化
template<typename T>
class Matrix { // 合理的泛化
// 矩阵运算
};
template<typename T>
class UniversalContainer { // 过度泛化,难以维护
// 试图满足所有需求的容器
};
性能优化指南
cpp
复制代码
// 1. 小函数模板放在头文件中
template<typename T>
inline T min(T a, T b) { // inline提示编译器优化
return a < b ? a : b;
}
// 2. 使用移动语义优化模板
template<typename T>
class Wrapper {
private:
T value_;
public:
// 完美转发构造函数
template<typename U>
Wrapper(U&& value) : value_(std::forward<U>(value)) {}
// 移动操作
Wrapper(Wrapper&&) = default;
Wrapper& operator=(Wrapper&&) = default;
};
// 3. 避免不必要的模板实例化
template<typename T>
void process_impl(T value) { // 内部实现
// 复杂逻辑
}
template<typename T>
void process(T value) { // 对外接口
if (value.is_valid()) { // 提前检查,避免不必要的实例化
process_impl(value);
}
}