C++模板元编程中的一些函数特性【完善中】
1.std::enable_if
std::enable_if
顾名思义,满足条件时类型有效。它只有在第一个模板参数为true的时候才会定义type。
1.1 源码实现:
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
1.2 使用示例:
1.2.1 基本用法:
typename std::enable_if<{BOOL 表达式}>::type
1.2.2 通过返回值使用:
对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看 tuple
的获取第 k 个元素的 get
函数。以下为另一种简单示例
template<class T,class... Args>
typename std::enable_if<std::is_trivially_constructible<T,Args&&...>::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<class T>
void destroy(
T* t, //第一个参数
typename std::enable_if< //第二个参数通过enable_if控制
std::is_trivially_destructible<T>::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 Integer,
typename = std::enable_if_t<std::is_integral<Integer>::value>
>
T(Integer) : m_type(int_t) {} //T<U, void>(U)
template <typename Floating,
typename = std::enable_if_t<std::is_floating_point<Floating>::value>
>
T(Floating) : m_type(float_t) {} // 错误:无法重载,因为其签名也是 T<U, void>(U)
};
/* 正确示例 */
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, int> = 0
>
T(Integer) : m_type(int_t) {} //仅当Integer为int时,签名为 T<int, int = 0>(int),否则SFINAE
template <typename Floating,
std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
>
T(Floating) : m_type(float_t) {} // 仅当Floating为浮点类型时,签名为,例如 T<double, int = 0>(double) 否则SFINAE
};
参考原文链接:https://blog.csdn.net/wbvalid/article/details/119352979