enable_if 是 C++ 标准库中的一个模板结构体,它用于条件编译和 SFINAE(Substitution Failure Is Not An Error)。enable_if 的主要作用是通过条件编译来控制模板的实例化,从而实现条件编译和 SFINAE。
1. enable_if 的基本用法如下:
#include <iostream>
#include <type_traits>
template<typename T>
struct MyStruct {
// 当 T 是指针类型时,MyStruct 被实例化
MyStruct(T* p) : ptr(p) {}
void print() const {
if (ptr != nullptr) {
std::cout << "Pointer value: " << *ptr << std::endl;
} else {
std::cout << "Pointer is null" << std::endl;
}
}
T* ptr;
};
int main() {
// 使用指针类型
int* p = nullptr;
MyStruct<int*> ms1(p);
// 使用非指针类型
int i = 0;
// MyStruct<int> ms2(i); // 错误:不能将 int 转换为 MyStruct<int>
// 调用 print 函数
ms1.print();
return 0;
}
2. enable_if 的另一个常见用法是在函数模板中使用它,以实现 SFINAE。例如:
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
print() {
std::cout << "Arithmetic type" << std::endl;
}
template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value, void>::type
print() {
std::cout << "Non-arithmetic type" << std::endl;
}
在这个例子中,std::enable_if 被用来控制 print 函数模板的实例化。当 T 是算术类型(如 int、float 等)时,std::is_arithmetic::value 为 true,std::enable_if 将生成一个类型 void,因此 print 被实例化,并输出 “Arithmetic type”。当 T 不是算术类型时,std::is_arithmetic::value 为 false,std::enable_if 将生成一个类型 void,因此 print 不被实例化,print 的另一个实例化版本将被选择。
总之,enable_if 是一个非常有用的工具,它可以用于条件编译和 SFINAE,从而使得模板编程更加灵活和安全。
实现利用偏特化模板
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
可以进一步阅读。
https://blog.csdn.net/wangx_x/article/details/122867422
3. unique_ptr 中删除指针,使用了SFINAE
template <typename _Up>
typename enable_if<is_convertible<_Up (*)[], _Tp (*)[]>::value>::type //注意这里的类型是数组的指针
//虽然允许派生类指针隐式的转换为基类指针,为了检查这种转换,我们要写成这样
//例如可以从non-const 转换为const,但不能从derived ** 转换为 base **
operator()(_Up *__ptr) const {
static_assert(sizeof(_Tp) > 0, "can't delete pointer to incomplete type");
//调用delete[]
delete[] __ptr;
}