作者:时光-Goslow | 来源:互联网 | 2023-07-11 21:11
1.std::enable_ifstd::enable_if顾名思义,满足条件时类型有效。它只有在第一个模板参数为true的时候才会定义type。1.1源码实现:template
1.std::enable_if
std::enable_if
顾名思义,满足条件时类型有效。它只有在第一个模板参数为true的时候才会定义type。
1.1 源码实现:
template
struct enable_if {};
template
struct enable_if { typedef T type; };
1.2 使用示例:
1.2.1 基本用法:
typename std::enable_if<{BOOL 表达式}>::type
1.2.2 通过返回值使用:
对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看 tuple
的获取第 k 个元素的 get
函数。以下为另一种简单示例
template
typename std::enable_if::value>::type
construct(T* t,Args&&... args)
{
std::cout <<"constructing trivially constructible T\n";
}
当T
和参数包...Args
中的对象都是std::is_trivially_constructible
时(即:可默认构造),std::enable_if
的结果为void
;
1.2.3 通过模板函数参数使用
有时定义的模板函数,只希望特定的类型可以调用,此时在函数参数中使用enable_if
template
void destroy(
T* t, //第一个参数
typename std::enable_if/第二个参数通过enable_if控制
std::is_trivially_destructible::value
>::type* = 0)
{
std::cout <<"destroying trivially destructible T\n";
}
若T
的类型满足is_trivially_destructible
的条件(即:可平凡析构),第二个参数的类型为void *
并取默认值void* = 0
;
需要注意的是,这样操作后,函数的签名实际上变为了void destroy(T*, void*)
。 这种操作的实质,是为了确保第一个参数是特定的类型(或满足特定的条件)。
常见错误
一个常见的错误是:声明了两个函数模板,它们只有默认模板实参不同。
这是非法的,因为默认的模板实参不是函数模板签名的一部分,并且声明两个具有相同签名的不同函数模板是非法的。
/*** 错误典型 ***/
struct T {
enum { int_t,float_t } m_type;
template typename = std::enable_if_t::value>
>
T(Integer) : m_type(int_t) {} //T(U)
template typename = std::enable_if_t::value>
>
T(Floating) : m_type(float_t) {} // 错误:无法重载,因为其签名也是 T(U)
};
/* 正确示例 */
struct T {
enum { int_t,float_t } m_type;
template std::enable_if_t::value, int> = 0
>
T(Integer) : m_type(int_t) {} //仅当Integer为int时,签名为 T(int),否则SFINAE
template std::enable_if_t::value, int> = 0
>
T(Floating) : m_type(float_t) {} // 仅当Floating为浮点类型时,签名为,例如 T(double) 否则SFINAE
};
参考原文链接:https://blog.csdn.net/wbvalid/article/details/119352979