关于std::enable_if用法的深入探究及相关代码解析请求
解析std::enable_if在模板类成员函数中的用法
我来帮你拆解这段用std::enable_if实现SFINAE(替换失败不是错误)的代码逻辑,一步步讲清楚它到底在做什么:
首先先把完整可理解的代码补全并贴出来:
#include <iostream> #include <cstdlib> #include <type_traits> #include <ios> using std::enable_if; using std::is_same; using std::boolalpha; using std::cout; using std::endl; template <typename T> struct S { T t; S(): t(static_cast<T>(NULL)) { } // 被注释的原始type()函数:不管T是什么类型都存在,仅运行期判断类型 // void type() { // cout << boolalpha; // cout << is_same<T,int>::value << endl; // } // 用enable_if改造后的成员模板函数:仅当T是int时才会被实例化 template <typename = typename enable_if<is_same<T,int>::value, T>::type> void type() { cout << boolalpha; cout << "T is int!" << endl; } };
1. 核心工具的作用
先搞懂代码里用到的两个编译期工具:
std::is_same<T, int>::value:这是一个编译期常量布尔值,只有当模板类的参数T和int完全相同时,它的值才是true,否则为false。它的作用是在编译期判断类型是否匹配。std::enable_if<Condition, Type>::type:这是SFINAE机制的核心工具之一。简单说:- 如果
Condition为true,::type就等于你指定的Type(这里是T),这个类型是有效的; - 如果
Condition为false,::type就不存在,编译器会直接跳过这个函数模板的实例化,不会报错(这就是"替换失败不是错误"的含义)。
- 如果
2. 成员函数的SFINAE实现逻辑
这段代码的核心是把enable_if用在成员函数的模板参数上,实现仅当T是int时,type()函数才存在:
- 首先要注意,这里的
type()是一个成员模板函数,不是普通成员函数——因为SFINAE需要在模板替换阶段生效,所以必须把enable_if放在模板参数里。 - 你原来的代码有两个小问题:缺少
typename(因为enable_if<...>::type是依赖于模板参数T的类型,需要用typename告诉编译器这是一个类型),以及模板参数需要一个默认值或者名称,我补全后的写法是最常用的形式:template <typename = typename enable_if<is_same<T,int>::value, T>::type>。
举两个实例化的例子:
- 当实例化
S<int>时:is_same<int, int>::value为true,enable_if<true, int>::type就是int,所以这个成员模板会被正常实例化,调用s_int.type()会输出T is int!。 - 当实例化
S<double>时:is_same<double, int>::value为false,enable_if<false, double>::type不存在,编译器会跳过这个函数模板的实例化——此时S<double>这个类里根本没有type()函数,如果你调用s_double.type()就会编译报错。
3. 和原始注释版type()的区别
被注释的原始type()是普通成员函数,不管T是什么类型,这个函数都会存在:调用时只是在运行期输出is_same的判断结果。而用enable_if改造后的版本是在编译期就决定了函数是否存在——如果T不是int,这个函数从一开始就不会被生成,属于更严格的编译期类型控制,能在编译阶段就拦截不符合条件的调用。
内容的提问来源于stack exchange,提问作者user9196120
相关产品推荐
相关产品推荐

