SFINAE(替换失败不是错误)原理与应用
请解释C++模板中的SFINAE(Substitution Failure Is Not An Error)原则、enable_if的典型用法,以及C++20 Concept对其的替代与改进。
回答
我还是少年
SFINAE:在模板实例化过程中,当替换模板参数失败时,编译器不会报错,而是从重载集合中移除该模板版本,继续尝试其他匹配。
典型用法 - std::enable_if:
// 仅对整型启用
template<typename T>
std::enable_if_t<std::is_integral_v<T>, void> func(T x) {
// 整型版本
}
// 仅对浮点型启用
template<typename T>
std::enable_if_t<std::is_floating_point_v<T>, void> func(T x) {
// 浮点版
}
进阶用法:
- 检测成员是否存在:检测某个类是否有特定成员函数,启用不同实现。
- 偏特化enable_if:
template<typename T, typename = void>
struct HasSize : false_type {};
template<typename T>
struct HasSize<T, void_t<decltype(declval<T>().size())>> : true_type {};
C++20 Concepts:SFINAE的现代替代,更简洁、错误信息更友好。
template<typename T> concept Integral = is_integral_v<T>;
template<Integral T> void func(T x) {}
比较:Concepts将SFINAE的意图表达提升到语言层面,错误信息从冗长模板错误变成简洁提示,编译速度更快。