Appearance
模板与模板元编程(Template & Metaprogramming)专题
HPC/Infra 面试偏重「模板能力」:类型萃取、编译期计算、SFINAE、CRTP、concepts、推导规则。这是区分「会用模板」和「懂元编程」的分水岭,常作为硬核区。
问题清单(含答案)
1. 函数模板 / 类模板 / 模板特化 / 偏特化 区别?
答案
函数模板/类模板是"蓝图",用具体类型实例化出真代码;特化给特定参数写专用实现,全特化固定全部参数、偏特化仍留模板参数(函数模板不能偏特化)。详见 basics.md。
2. 模板的「编译期实例化」是什么?为什么模板放头文件?
答案
编译器针对每种用到的类型"生成"一份具体代码(实例化)。定义必须放头文件,因为编译器要看到完整定义才能实例化、无跨编译单元链接。
3. 类型萃取 type_traits?remove_reference/is_same 原理?
答案
编译期"查询/变换类型"的元函数。remove_reference<T> 用偏特化匹配 T&/T&& 剥掉引用;is_same 用 is_same<T,T> 特化判相等。详见 type-traits.md。
4. SFINAE 原理与 enable_if?
答案
SFINAE = 替换失败非错误,候选匹配失败不报错而是从重载集移除。enable_if<条件, T> 据此做条件模板重载。详见 sfinae.md。
5. constexpr 元编程?
答案
用 constexpr 函数/变量在编译期计算;C++14 起可写循环、C++17 可 if constexpr 剪枝,替代 C++03 的模板递归。详见 constexpr-meta.md。
6. CRTP 与静态多态(对比虚函数)?
答案
class X : Base<X>,基类用 static_cast 安全向下转型实现静态多态,无虚函数运行时开销;虚函数是运行期多态。详见 crtp.md。
7. 折叠表达式 fold (C++17)?
答案
(pack op ...) 把参数包折叠成表达式(如求和 (args + ...)),替代递归展开。
8. concepts(C++20) 如何替代 SFINAE?
答案
用 concept/requires 直接表达类型约束,重载更简洁、报错信息更清晰(不再 SFINAE 那一长串),也用于约束 auto。
9. 模板推导规则倒错题?
答案
值传递剥引用和顶层 const、数组/函数退化成指针;引用折叠 &&+&→&、&&+&&→&&;auto 推导与模板推导完全一致。详见 deduction.md。
10. std::is_same_v + if constexpr 剪枝?
答案
if constexpr (is_same_v<T,int>) 是编译期分支,只实例化命中的分支,未用分支不编译(避免不同类型走同一份代码出错)。
子文档
| 文件 | 内容 |
|---|---|
index.md | 本总览 |
basics.md | 模板基础、实例化、特化/偏特化、非类型参数 |
type-traits.md | type_traits 原理、remove_、is_、conditional、tuple 实现模型 |
sfinae.md | SFINAE、enable_if、void_t 探测惯用法 |
constexpr-meta.md | constexpr 函数 C++14、编译期递归、if constexpr 剪枝 |
crtp.md | CRTP / 静态多态 / 混入(mixin) |
concepts.md | C++20 requires/concept 语法与 use-case |
deduction.md | 模板参数推导深规则(引用折叠、auto 对应)+ 经典题 |
学习顺序建议
先 basics → sfinae/type-traits(工具)→ constexpr-meta(计算)→ crtp(模式)→ concepts(新写法)。每篇末尾有自测/推导题,盖住答案先自己做。
提示:HPC/AI infra 里真正的「元编程」大量用于编译期维度展开、生成访问代码、policy-based 设计、kernel 分派,而不是面试背 SFINAE 诅咒——理解「为什么需要」(编译期选型/性能/诊断)比炫技更重要。