6月1日 10:30
C++ 模板特化和偏特化怎么用?全特化/偏特化/SFINAE 详解
模板特化允许为特定类型提供与通用版本不同的实现。全特化指定所有模板参数,为某一具体类型提供完全定制版本,全特化后的模板不再有模板参数。偏特化仅适用于类模板和变量模板,对部分参数做约束,保留剩余参数的通用性。例如 template<typename T> class A<T*> 为所有指针类型提供统一实现,T 仍为参数。函数模板不支持偏特化,只能用重载或全特化替代。SFINAE(替换失败并非错误)是模板元编程的基础规则:在模板实参替换阶段,若某个候选的替换导致类型错误,该候选被静默剔除而非编译报错。std::enable_if 利用 SFINAE,通过条件编译控制模板是否参与重载决议,是 C++17 之前约束模板的主要手段。
追问
全特化和偏特化的实例化优先级如何?
编译器优先选择最特化的版本。全特化比偏特化更特化,偏特化比通用模板更特化。若两个偏特化同等特化则二义报错。
函数模板为什么不能偏特化?
函数模板支持重载,重载已能实现类似效果。若允许偏特化,与重载决议的交互会带来复杂歧义,标准因此禁止。
enable_if 的 ::type 在条件为 false 时是什么?
不存在。enable_if<false, T> 没有嵌套 type 类型,导致替换失败触发 SFINAE,该模板被剔除。C++14 提供了 enable_if_t 别名简化写法。
C++17 的 if constexpr 能替代 SFINAE 吗?
部分场景可以。if constexpr 在编译期根据条件丢弃分支代码,比 SFINAE 更直观。但它无法控制函数签名层面的重载决议,仍需 SFINAE 或 C++20 concepts。