📘 本篇专注两个深度主题:CRTP(Curiously Recurring Template Pattern)奇异递归模板模式与 类型萃取(type traits)技巧。这是现代 C++ 泛型设计和高性能库实现的核心技术。我们以实用出发,通过精炼讲解 + 具体可跑的示例,带你理解底层原理并学会实战使用。
🎯 今日目标
核心技术 | 掌握重点 |
---|---|
CRTP 模式 | 学会如何通过模板实现静态多态与接口内联展开 |
类型萃取 traits | 理解 std::is_xxx、enable_if 的构造原理与用法 |
高级组合 | 将两者结合设计更灵活可配置的类型行为系统 |
✅ 一、CRTP 模式:静态多态与行为注入
🔸 结构示例
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
class Foo : public Base<Foo> {
public:
void implementation() {
std::cout << "Foo::implementation()" << std::endl;
}
};
int main() {
Foo f;
f.interface(); // 输出 Foo::implementation()
}
📌 本质说明:
- 基类模板以派生类为参数,构成编译期绑定的多态结构
- 避免虚函数开销,允许内联展开,适用于性能敏感场景
📌 使用场景:
- STL 算法、Eigen 数学库
- 状态机框架、策略注入系统
✅ 二、类型萃取(traits):让类型具备“可判定性”
🔸 自定义 is_pointer 判断逻辑
template<typename T>
struct is_pointer {
static const bool value = false;
};
template<typename T>
struct is_pointer<T*> {
static const bool value = true;
};
std::cout << is_pointer<int>::value; // 输出 0
std::cout << is_pointer<int*>::value; // 输出 1
📌 本质说明:
- 类型萃取用于“在编译期判断某类型是否满足某种结构”
- 是
std::is_xxx
系列的实现基础
📌 实战用途:
- 模板选择(启用/禁用特定函数)
- 编译期报错控制(static_assert)
✅ 三、enable_if 结合 CRTP 实现“类型约束接口”
#include <type_traits>
template<typename T>
class Printable {
public:
void print() {
static_assert(std::is_arithmetic<T>::value, "T 必须是数值类型");
std::cout << "Value = " << value << std::endl;
}
T value;
};
Printable<int> a{10};
a.print(); // OK
// Printable<std::string> b{"test"}; // 编译期报错
📌 技术组合说明:
std::is_arithmetic<T>
用于类型判断static_assert
编译期断言,提升类型安全
✅ 四、综合设计:CRTP + traits 定义行为接口系统
// 是否支持加法的特征检测
template<typename T, typename = void>
struct has_plus : std::false_type {};
template<typename T>
struct has_plus<T, decltype(void(std::declval<T>() + std::declval<T>()))> : std::true_type {};
// CRTP 接口
template<typename Derived, typename T>
class Addable {
public:
void try_add() {
if constexpr (has_plus<T>::value) {
T result = static_cast<Derived*>(this)->get() + static_cast<Derived*>(this)->get();
std::cout << "Add result: " << result << std::endl;
} else {
std::cout << "Not addable." << std::endl;
}
}
};
class MyInt : public Addable<MyInt, int> {
public:
int get() const { return 10; }
};
class MyVoid : public Addable<MyVoid, void> {
public:
void get() const {}
};
📌 技术亮点:
- 通过
void_t
+ declval 检测表达式是否合法 - 配合
if constexpr
提供“条件编译行为” - 使用 CRTP 让接口行为自动绑定在派生类上
📚 总结回顾
- CRTP:模板 + 继承,带来静态多态与零成本内联
- traits:构建类型元信息判断系统的基石
- enable_if / static_assert / if constexpr:现代 C++ 类型安全的守护者
- 两者结合是泛型编程与模板策略模式的进阶门槛
下一篇是否继续进入 Day 8:深入 std::function
、lambda
表达式与函数对象?或希望将 CRTP + traits 应用于一个完整架构中(如插件系统、策略注入)?