1. C++模板进阶核心概念解析
当我们在C++中谈到模板进阶时,实际上是在探讨如何让泛型编程更加灵活和强大。模板作为C++泛型编程的基石,其进阶用法能够显著提升代码的复用性和运行效率。让我们从一个实际案例开始:假设你需要编写一个数学库,其中包含对多种数据类型(int, float, double等)的向量运算。使用基础模板可以解决类型泛化问题,但当遇到特殊需求时(比如针对bool类型的特化处理),就需要模板进阶技术了。
模板进阶主要包含以下几个关键方向:非类型模板参数让我们可以在编译期传递常量值;全特化和偏特化允许我们对特定类型或类型组合进行定制化实现;模板的分离编译则关系到工程组织方式。这些技术共同构成了现代C++模板编程的核心武器库。
重要提示:模板代码在编译时展开,因此任何模板相关的错误都会在编译期暴露。这既是优势(早期错误检测),也可能导致晦涩的错误信息。
2. 非类型模板参数深度剖析
2.1 基本语法与应用场景
非类型模板参数允许我们将值而不仅是类型作为模板参数。其标准语法如下:
template <typename T, int N> class FixedArray { public: T& operator[](int index) { return data_[index]; } private: T data_[N]; // 固定大小的数组 };这里的int N就是非类型参数,它必须是:
- 整型或枚举类型
- 指针或引用(指向具有静态存储期的对象)
- std::nullptr_t
典型应用场景包括:
- 固定大小容器的实现(如上面的FixedArray)
- 数学计算中的编译期常数(如矩阵维度)
- 策略模式中的策略选择标记
2.2 使用限制与实战技巧
非类型参数在C++17后得到了显著增强,但仍有一些关键限制需要注意:
- 浮点型和类类型不能作为非类型参数(C++20部分放宽)
- 参数必须是编译期常量表达式
- 指针/引用参数有严格的链接性要求
一个实用的技巧是结合auto推导(C++17起):
template <auto value> void printValue() { std::cout << value << std::endl; } printValue<42>(); // 整型 printValue<'A'>(); // 字符3. 模板特化技术详解
3.1 全特化实现与最佳实践
全特化是指为模板参数提供完全确定的类型实现。以std::vector的bool特化为例:
// 主模板 template <typename T> class Vector { // 通用实现 }; // 全特化版本 template <> class Vector<bool> { // 针对bool的位压缩实现 void push_back(bool value) { // 特殊处理逻辑 } };全特化的关键特征:
- template<>前缀表明这是特化版本
- 类名后的 指定了具体类型
- 可以与主模板有完全不同的实现
经验之谈:全特化常用于优化特定类型的性能,或者处理特殊类型的边界情况。但要注意保持接口一致性。
3.2 偏特化的艺术与应用
偏特化(C++标准中称为部分特化)允许我们对部分模板参数进行特化。典型模式:
// 主模板 template <typename T, typename Allocator> class List { /*...*/ }; // 偏特化:第二个参数固定为MyAlloc template <typename T> class List<T, MyAlloc> { /*...*/ }; // 偏特化:两个指针类型 template <typename T, typename U> class List<T*, U*> { /*...*/ };偏特化的强大之处在于可以:
- 针对类型特征进行特化(如指针、引用、const等)
- 构建类型转换规则
- 实现编译期多态
一个实用的设计模式是"标签分发",结合类型特征使用:
template <typename T> void process(T value, std::true_type) { // 针对整数类型的实现 } template <typename T> void process(T value, std::false_type) { // 其他类型的实现 } // 调用接口 template <typename T> void process(T value) { process(value, std::is_integral<T>{}); }4. 模板分离编译的工程实践
4.1 问题本质与解决方案
模板分离编译的核心挑战源于C++的编译模型。考虑以下典型错误场景:
// util.h template <typename T> T add(T a, T b); // util.cpp template <typename T> T add(T a, T b) { return a + b; } // main.cpp #include "util.h" int main() { add(1, 2); // 链接错误! }这是因为模板代码需要在实例化时可见。解决方案包括:
- 显式实例化(在.cpp文件中):
template int add<int>(int, int);- 包含模式(推荐):
// util.hpp template <typename T> T add(T a, T b) { return a + b; }- 使用extern模板(C++11)减少编译时间:
// header.h extern template class std::vector<int>;4.2 大型项目中的模板组织策略
在大型项目中,合理的模板代码组织至关重要:
- 模块化设计:
- 将模板声明和实现都放在.hpp文件中
- 按功能划分模板组件
- 使用inline命名空间管理版本
- 编译防火墙技术:
// 接口 template <typename T> class Widget { public: void operation(); private: struct Impl; std::unique_ptr<Impl> pImpl; }; // 实现 template <typename T> struct Widget<T>::Impl { // 具体实现细节 }; template <typename T> void Widget<T>::operation() { pImpl->operation(); }- 编译期检测:
static_assert(std::is_default_constructible_v<T>, "T must be default constructible");5. 模板元编程进阶技巧
5.1 SFINAE与enable_if的现代用法
SFINAE(Substitution Failure Is Not An Error)是模板元编程的核心机制。现代C++中推荐使用std::enable_if:
template <typename T> auto foo(T t) -> std::enable_if_t<std::is_integral_v<T>, void> { // 仅对整数类型有效 } // C++20概念更简洁 template <std::integral T> void bar(T t) { /*...*/ }实用技巧:
- 结合类型特征进行重载解析
- 用于构造函数模板防止意外隐式转换
- 创建灵活的接口适配层
5.2 变参模板的高级应用
变参模板(Variadic Templates)为模板编程带来了极大灵活性:
template <typename... Ts> class Tuple {}; // 递归处理参数包 template <typename T, typename... Rest> void print(T&& t, Rest&&... rest) { std::cout << t; if constexpr (sizeof...(rest) > 0) { std::cout << ", "; print(std::forward<Rest>(rest)...); } } // 折叠表达式(C++17) template <typename... Args> auto sum(Args... args) { return (args + ...); }实际应用场景:
- 类型安全的printf实现
- 多态函数包装器
- 编译期数据结构构建
6. 模板实战中的陷阱与优化
6.1 常见编译错误解析
模板相关的编译错误往往令人生畏。以下是典型错误及解决方法:
- 模板实例化失败:
error: no matching function for call to 'foo'检查:模板参数是否满足所有约束条件
- 歧义的重载:
error: call of overloaded 'bar(int)' is ambiguous解决方案:使用SFINAE或C++20概念明确区分重载
- 链接错误:
undefined reference to `MyClass<int>::func()'确保模板定义在实例化时可见
6.2 性能优化策略
模板虽然强大,但也可能带来代码膨胀等问题。优化策略包括:
- 显式实例化常用类型:
template class std::vector<int>;- 使用extern模板声明:
extern template class std::map<std::string, int>;- 代码去重技术:
template <typename T> void commonLogic(T t) { // 共享实现 } template <typename T> void optimizedForInt(T t) { if constexpr (std::is_same_v<T, int>) { // 特殊处理 } else { commonLogic(t); } }- 编译期计算:
template <size_t N> struct Factorial { static constexpr size_t value = N * Factorial<N-1>::value; }; template <> struct Factorial<0> { static constexpr size_t value = 1; };7. 现代C++中的模板新特性
7.1 C++17的模板增强
- if constexpr - 编译期分支:
template <typename T> auto getValue(T t) { if constexpr (std::is_pointer_v<T>) { return *t; } else { return t; } }- 结构化绑定与模板:
template <typename T> void processPair(const T& pair) { auto& [first, second] = pair; // 使用first和second }7.2 C++20的革命性变化
- 概念(Concepts):
template <typename T> concept Numeric = std::is_arithmetic_v<T>; template <Numeric T> T square(T x) { return x * x; }- 约束auto:
Numeric auto add(Numeric auto a, Numeric auto b) { return a + b; }- 模板lambda:
auto make_adder = []<typename T>(T x) { return [x]<typename U>(U y) { return x + y; }; };8. 模板在标准库中的应用实例
8.1 STL中的模板设计模式
标准模板库是模板技术的集大成者。分析几个典型设计:
- 迭代器模式:
template <typename InputIt, typename T> InputIt find(InputIt first, InputIt last, const T& value);- 策略模式:
template < typename T, typename Allocator = std::allocator<T>, typename Compare = std::less<T> > class set;- 类型萃取:
template <typename Iter> using value_type_t = typename std::iterator_traits<Iter>::value_type;8.2 自定义分配器案例
通过模板实现自定义内存管理:
template <typename T> class PoolAllocator { public: using value_type = T; T* allocate(size_t n) { return static_cast<T*>(pool_.allocate(n * sizeof(T))); } void deallocate(T* p, size_t n) { pool_.deallocate(p, n * sizeof(T)); } private: MemoryPool pool_; }; // 使用 std::vector<int, PoolAllocator<int>> vec;9. 模板元编程实战案例
9.1 编译期字符串处理
利用模板在编译期操作字符串:
template <size_t N> struct FixedString { char buf[N + 1] = {}; constexpr FixedString(const char (&s)[N]) { std::copy_n(s, N, buf); } }; template <FixedString S> struct DebugMessage { static constexpr auto message = S; }; // 使用 DebugMessage<"Hello, Template!"> msg;9.2 类型安全的接口绑定
创建类型安全的回调系统:
template <typename... Args> class Event { public: using Callback = std::function<void(Args...)>; void subscribe(Callback cb) { callbacks_.push_back(std::move(cb)); } void notify(Args... args) { for (auto& cb : callbacks_) { cb(args...); } } private: std::vector<Callback> callbacks_; }; // 使用 Event<int, std::string> onData; onData.subscribe([](int id, std::string name) { std::cout << id << ": " << name << std::endl; });10. 模板代码的测试与调试
10.1 静态断言与概念检查
编译期验证模板约束:
template <typename T> class Container { static_assert(std::is_default_constructible_v<T>, "T must be default constructible"); // ... }; // C++20概念约束 template <typename T> requires std::copyable<T> class CopyableContainer {};10.2 模板实例化追踪
调试技巧:
- 使用
-ftime-report(GCC/Clang)分析模板实例化时间 - 通过
__PRETTY_FUNCTION__输出实例化信息:
template <typename T> void debug() { std::cout << __PRETTY_FUNCTION__ << std::endl; }- 限制递归深度:
template <int N> void recurse() { static_assert(N < 10, "Recursion depth exceeded"); recurse<N+1>(); } template <> void recurse<10>() {}11. 跨平台模板开发注意事项
11.1 ABI兼容性问题
不同编译器对模板的处理可能有差异:
- 名称修饰规则不同
- 实例化机制差异
- 类型布局可能变化
解决方案:
- 显式实例化公共接口
- 使用PIMPL模式隔离实现
- 避免暴露模板参数中的平台相关类型
11.2 编译器特定行为
- MSVC的
__if_exists扩展:
template <typename T> void check() { __if_exists(T::specialMethod) { // MSVC特有语法 } }- GCC的
visibility属性:
template <typename T> class __attribute__((visibility("default"))) ExportedClass {};12. 模板与其它特性的结合
12.1 模板与constexpr的协同
编译期计算的最佳组合:
template <typename T, size_t N> constexpr auto arraySize(const T (&)[N]) noexcept { return N; } // 使用 int arr[] = {1, 2, 3}; constexpr size_t size = arraySize(arr);12.2 模板与异常安全
模板代码中的异常处理策略:
template <typename F, typename... Args> auto invokeSafe(F&& f, Args&&... args) noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...))) { try { return std::forward<F>(f)(std::forward<Args>(args)...); } catch (...) { // 统一异常处理 throw; } }13. 模板代码的性能分析
13.1 代码膨胀评估
检测模板实例化情况:
- GCC/Clang的
-fdump-class-hierarchy - 生成映射文件分析符号表
- 使用
nm或objdump工具
优化策略:
- 提取公共代码到非模板基类
- 使用extern模板减少重复实例化
- 考虑运行时多态替代深层次模板
13.2 编译时间优化
加速模板编译的技巧:
- 预编译头文件(PCH)
- 显式实例化常用类型
- 使用C++20模块替代头文件
- 并行编译(-j选项)
- 分布式编译工具(如distcc)
14. 模板设计模式与惯用法
14.1 CRTP(奇异递归模板模式)
静态多态实现:
template <typename Derived> class Base { public: void interface() { static_cast<Derived*>(this)->implementation(); } }; class Derived : public Base<Derived> { public: void implementation() { std::cout << "Derived implementation" << std::endl; } };应用场景:
- 静态多态
- 编译期接口检查
- 避免虚函数开销
14.2 类型擦除技术
std::function的实现原理:
template <typename T> class AnyCallable { struct Concept { virtual ~Concept() = default; virtual T operator()(/*args*/) = 0; }; template <typename F> struct Model : Concept { F f; T operator()(/*args*/) override { return f(/*args*/); } }; std::unique_ptr<Concept> impl_; public: template <typename F> AnyCallable(F&& f) : impl_(new Model<std::decay_t<F>>{std::forward<F>(f)}) {} T operator()(/*args*/) { return (*impl_)(/*args*/); } };15. 模板的未来发展趋势
15.1 C++23中的模板改进
- 显式模板参数列表:
std::vector v = {1, 2, 3}; auto x = foo<int>(v); // 显式指定模板参数- if constexpr扩展:
template <typename T> void process(T t) { if constexpr (requires { t.special(); }) { t.special(); } }15.2 反射与模板的结合
未来可能的特性:
template <typename T> void inspect() { constexpr auto name = reflexpr(T).name; std::cout << "Type name: " << name << std::endl; }16. 模板进阶学习资源
16.1 经典书籍推荐
- 《C++ Templates: The Complete Guide》2nd Edition
- 《Modern C++ Design》Andrei Alexandrescu
- 《C++ Template Metaprogramming》David Abrahams
16.2 实用工具链
- Compiler Explorer:在线查看模板实例化
- CppInsights:可视化模板展开过程
- Clang AST Matcher:分析模板代码结构
17. 模板工程实践问答
17.1 何时避免使用模板?
虽然模板功能强大,但在以下场景应谨慎使用:
- 二进制接口(ABI)稳定性要求高的场合
- 需要动态加载的插件系统
- 编译时间敏感的项目
- 团队中C++经验不足的情况
17.2 如何设计模板友好的API?
良好模板API的设计原则:
- 最小化模板参数数量
- 使用概念或SFINAE明确约束
- 提供清晰的错误信息(static_assert)
- 保持接口简单直观
- 文档化类型要求和行为预期
18. 模板调试高级技巧
18.1 实例化堆栈分析
当遇到深层模板实例化错误时:
- GCC使用
-ftemplate-backtrace-limit=100 - Clang使用
-fno-elide-type - 逐步注释代码定位问题源头
18.2 类型输出技巧
运行时输出类型信息:
template <typename T> void printType() { std::cout << __PRETTY_FUNCTION__ << std::endl; } // 或使用typeid(有限信息) std::cout << typeid(T).name() << std::endl;19. 模板与并发编程
19.1 线程安全模板设计
确保模板代码的线程安全性:
template <typename T> class ThreadSafeQueue { public: void push(T value) { std::lock_guard<std::mutex> lock(mutex_); queue_.push(std::move(value)); } bool try_pop(T& value) { std::lock_guard<std::mutex> lock(mutex_); if (queue_.empty()) return false; value = std::move(queue_.front()); queue_.pop(); return true; } private: std::queue<T> queue_; mutable std::mutex mutex_; };19.2 原子操作的模板封装
template <typename T> class Atomic { public: Atomic() = default; explicit Atomic(T desired) : value_(desired) {} T load(std::memory_order order = std::memory_order_seq_cst) const { return value_.load(order); } void store(T desired, std::memory_order order = std::memory_order_seq_cst) { value_.store(desired, order); } private: std::atomic<T> value_; };20. 模板性能基准测试
20.1 编译期与运行期权衡
测试不同实现方式的性能差异:
// 编译期计算 template <size_t N> struct Factorial { /*...*/ }; // 运行期计算 size_t factorial(size_t n) { /*...*/ } // 基准测试 BENCHMARK("CompileTime", [] { volatile auto result = Factorial<10>::value; }); BENCHMARK("Runtime", [] { volatile auto result = factorial(10); });20.2 代码膨胀测量
使用工具分析模板实例化影响:
nm --demangle --size-sort a.out- Bloaty McBloatface工具
- 编译器特定的size分析选项
21. 模板代码审查要点
21.1 常见问题检查清单
审查模板代码时应关注:
- 是否所有模板参数都被使用?
- 约束条件是否充分明确?
- 错误信息是否友好?
- 是否存在意外隐式转换风险?
- 二进制兼容性是否考虑?
21.2 可读性改进建议
提升模板代码可读性的技巧:
- 使用有意义的模板参数名
- 适当添加注释解释复杂逻辑
- 使用using别名简化复杂类型
- 保持合理的缩进和格式
- 将复杂元编程逻辑提取到单独组件
22. 模板与移动语义
22.1 完美转发实现
通用包装器设计:
template <typename F, typename... Args> auto wrapper(F&& f, Args&&... args) { return std::forward<F>(f)(std::forward<Args>(args)...); }22.2 移动感知容器
实现支持移动语义的容器:
template <typename T> class Vector { public: void push_back(const T& value) { // 拷贝构造 } void push_back(T&& value) { // 移动构造 } template <typename... Args> void emplace_back(Args&&... args) { // 原地构造 } };23. 模板与异常安全
23.1 强异常保证实现
确保模板操作的原子性:
template <typename T> class Stack { public: void push(const T& value) { auto new_top = new Node(value, top_); top_ = new_top; // 仅当new成功后才修改状态 } private: struct Node { T value; Node* next; }; Node* top_ = nullptr; };23.2 资源管理模板
通用资源处理器:
template <typename T, auto Deleter> class ResourceHandle { public: explicit ResourceHandle(T handle) : handle_(handle) {} ~ResourceHandle() { if (handle_) Deleter(handle_); } // 禁止拷贝,允许移动 ResourceHandle(const ResourceHandle&) = delete; ResourceHandle(ResourceHandle&& other) noexcept : handle_(std::exchange(other.handle_, nullptr)) {} private: T handle_; }; // 使用 using FileHandle = ResourceHandle<FILE*, fclose>;24. 模板与多范式编程
24.1 函数式编程支持
实现高阶函数:
template <typename F> auto curry(F f) { return [f](auto... args1) { return [f, args1...](auto... args2) { return f(args1..., args2...); }; }; } auto add = [](int a, int b) { return a + b; }; auto curriedAdd = curry(add); auto addFive = curriedAdd(5); std::cout << addFive(3); // 输出824.2 面向方面编程
使用模板实现横切关注点:
template <typename F> auto logCall(F f) { return [f](auto&&... args) { std::cout << "Calling with " << sizeof...(args) << " arguments\n"; auto result = f(std::forward<decltype(args)>(args)...); std::cout << "Returned: " << result << "\n"; return result; }; } auto loggedAdd = logCall(add); loggedAdd(2, 3); // 输出调用和返回信息25. 模板元编程性能考量
25.1 编译期计算开销分析
虽然编译期计算可以提升运行时性能,但需要考虑:
- 编译时间增长
- 编译器内存使用
- 调试难度增加
平衡策略:
- 限制递归深度
- 使用constexpr函数替代模板元编程
- 分层设计,核心部分用模板,外围用常规代码
25.2 模板实例化缓存
现代编译器的优化策略:
- 重复实例化检测
- 预编译头文件中的模板实例
- 显式实例化指导优化
可以通过编译选项控制:
-fno-implicit-templates(GCC)/template:verbose(MSVC)
26. 跨语言模板交互
26.1 与C接口的兼容性
导出模板实例供C使用:
extern "C" { // 显式实例化 template class std::vector<int>; void process_ints(int* arr, size_t size) { std::vector<int> vec(arr, arr + size); // 处理逻辑 } }26.2 与其他语言的互操作
Python扩展示例(使用pybind11):
template <typename T> class Matrix { /*...*/ }; // 显式实例化并绑定 PYBIND11_MODULE(matrix, m) { py::class_<Matrix<double>>(m, "MatrixDouble") .def(py::init<>()); py::class_<Matrix<float>>(m, "MatrixFloat") .def(py::init<>()); }27. 模板代码版本管理
27.1 兼容性维护策略
长期维护模板库的建议:
- 使用内联命名空间管理版本:
namespace lib { inline namespace v1 { template <typename T> class Widget { /*...*/ }; } namespace v2 { template <typename T> class Widget { /*...*/ }; } }- 提供迁移指南和兼容层
- 使用静态断言检测过时代码
27.2 弃用模板技巧
标记过时模板:
template <typename T> [[deprecated("Use NewTemplate instead")]] class OldTemplate {};或者使用static_assert提供更友好的消息:
template <typename T> class OldTemplate { static_assert(!std::is_same_v<T, T>, "OldTemplate is deprecated, use NewTemplate instead"); };28. 模板设计模式案例
28.1 策略模式模板实现
编译期策略选择:
template <typename SortingStrategy> class SortedCollection { public: void sort() { SortingStrategy::sort(data_.begin(), data_.end()); } private: std::vector<int> data_; }; struct QuickSort { static void sort(auto begin, auto end) { /*...*/ } }; struct MergeSort { static void sort(auto begin, auto end) { /*...*/ } }; // 使用 SortedCollection<QuickSort> quick; SortedCollection<MergeSort> merge;28.2 访问者模式模板化
template <typename... Types> class Visitor; template <typename T, typename... Rest> class Visitor<T, Rest...> : public Visitor<Rest...> { public: using Visitor<Rest...>::visit; virtual void visit(T&) = 0; }; template <typename T> class Visitor<T> { public: virtual void visit(T&) = 0; }; // 使用 using ShapeVisitor = Visitor<Circle, Square>;29. 模板与概念约束
29.1 概念定义最佳实践
设计良好的概念:
template <typename T> concept Drawable = requires(T t, std::ostream& os) { { t.draw(os) } -> std::same_as<void>; }; template <Drawable T> void render(const T& shape) { shape.draw(std::cout); }29.2 概念组合与重用
构建复杂约束:
template <typename T> concept Numeric = std::integral<T> || std::floating_point<T>; template <typename T> concept Addable = requires(T a, T b) { { a + b } -> std::same_as<T>; }; template <typename T> concept NumericAddable = Numeric<T> && Addable<T>;30. 模板测试覆盖率
30.1 单元测试策略
模板代码的测试方法:
- 显式实例化测试用例:
template class MyTemplate<int>; template class MyTemplate<std::string>;- 类型参数化测试(使用GTest):
template <typename T> class TemplateTest : public ::testing::Test {}; using TestTypes = ::testing::Types<int, float, std::string>; TYPED_TEST_SUITE(TemplateTest, TestTypes); TYPED_TEST(TemplateTest, Basic) { MyTemplate<TypeParam> instance; // 测试逻辑 }30.2 覆盖率分析技巧
确保全面测试:
- 使用不同类型组合测试边界条件
- 验证概念约束的失败情况
- 测试特化版本的独特行为
- 检查移动/拷贝语义的正确性
工具支持:
- gcov/lcov
- LLVM coverage
- Visual Studio coverage工具
31. 模板文档规范
31.1 Doxygen注释示例
模板参数的文档化:
/** * @brief A generic container with fixed capacity * @tparam T The type of elements stored in the container * @tparam N The maximum number of elements (must be positive) */ template <typename T, size_t N> class FixedContainer { static_assert(N > 0, "Capacity must be positive"); };31.2 需求说明格式
明确模板参数要求:
/* * Requirements on T: * - Must be default constructible * - Must provide operator< for ordering * - Copy constructor must not throw */ template <typename T> class SortedCollection { /*...*/ };32. 模板调试符号处理
32.1 调试信息优化
减少调试符号大小:
- GCC的
-gno-strict-dwarf和-gno-record-gcc-switches - 限制调试信息深度
- 分离调试信息(-gsplit-dwarf)
32.2 可调试模板设计
提升模板代码可调试性:
- 避免过深的嵌套实例化
- 提供有意义的类型别名
- 使用static_assert添加约束检查
- 保持错误信息友好
33. 模板与constexpr融合
33.1 编译期数据结构
constexpr容器实现:
template <typename T, size_t N> struct ConstexprArray { constexpr T& operator[](size_t i) { return data[i]; } T data[N]; size_t size = N; }; constexpr auto squares = [] { ConstexprArray<int, 10> arr{}; for (size_t i = 0; i < arr.size; ++i) { arr[i] = i * i; } return arr; }();33.2 混合计算模式
编译期与运行期协同:
template <typename T, auto Init> class CachedValue { public: constexpr CachedValue() : value_(Init) {} constexpr T get() const { return value_; } constexpr void set(T value) { value_ = value; } private: T value_; }; // 编译期初始化,运行期修改 CachedValue<int, 42> cache;34. 模板安全编程
34.1 类型安全验证
防御性模板设计:
template <typename T> class SafeContainer { static_assert(!std::is_pointer_v<T>, "Raw pointers are not allowed for safety"); // ... };34.2 边界检查策略
安全访问模式:
template <typename T, size_t N> class CheckedArray { public: const T& at(size_t i) const { if (i >= N) throw std::out_of_range("Index out of bounds"); return data_[i]; } private: T data_[N]; };35. 模板性能调优
35.1 内联优化指导
影响代码生成的技巧:
template <typename T> class InlineWrapper { public: __attribute__((always_inline)) T operator()(T x) const { return x * x; } };35.2 分支预测提示
优化条件判断:
template <typename T> T abs(T x) { if (__builtin_expect(x < 0, 0)) { return -x; } return x; }36. 模板与协程
36.1 协程框架模板
通用协程任务:
template <typename T> struct Task { struct promise_type { Task get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_value(T value) { result = value; } void unhandled_exception() { std::terminate(); } T result; }; T get() { return handle.promise().result; } private: std::coroutine_handle<promise_type> handle; };36.2 模板化协程参数
template <typename T> Task<T> asyncCompute() { co_return T{}; }37. 模板与SIMD
37.1 向量化模板
通用SIMD包装:
template <typename T, size_t Width> struct SIMDVector { using IntrinsicType = __attribute__((__vector_size__(Width * sizeof(T)))) T; SIMD