1 SFINAE。
2 条件特化。可用作额外的函数参数(不可应用于运算符重载)、返回类型(不可应用于构造函数与析构函数),或类模板或函数模板形参。
函数参数:
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T>
T addT(T value, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr)
{
return value + 10;
}
template <typename T>
T addT(T value, typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr)
{
return value + 5;
}
int main()
{
int d = 10;
double f = 20;
d = addT(d);
f = addT(f);
return 0;
}
单独看这个例子是比较模糊,因为编译器做了自动补充:d = addT(d, nullptr);通过如下网站可以展开上面代码
#include <iostream>
#include <type_traits>
using namespace std;
template<typename T>
T addT(T value, typename std::enable_if<std::is_integral<T>::value, T>::type *)
{
return operator+(value, 10);
}
/* First instantiated from: insights.cpp:22 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
int addT<int>(int value, typename std::enable_if<std::is_integral<int>::value, int>::type *)
{
return value + 10;
}
#endif
template<typename T>
T addT(T value, typename std::enable_if<std::is_floating_point<T>::value, T>::type *)
{
return operator+(value, 5);
}
/* First instantiated from: insights.cpp:23 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double addT<double>(double value, typename std::enable_if<std::is_floating_point<double>::value, double>::type *)
{
return value + 5;
}
#endif
int main()
{
int d = 10;
double f = 20;
d = addT(d, nullptr);
f = addT(f, nullptr);
return 0;
}
函数返回值:
#include <type_traits>
#include <iostream>
template <typename T>
typename std::enable_if <std::is_integral<T>::value, T>::type addT(T value)
{
return value + 10;
}
template <typename T>
typename std::enable_if <std::is_floating_point<T>::value, T>::type addT(T value)
{
return value + 5.0;
}
int main()
{
int d = 10;
double f = 20;
d = addT(d); //d = 20
f = addT(f); //f = 25.000000000
return 0;
}
std::is_integral 用法参考:https://cplusplus.com/reference/type_traits/is_integral/
编译展开后的代码如下:
#include <type_traits>
#include <iostream>
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type addT(T value)
{
return value + 10;
}
/* First instantiated from: insights.cpp:20 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::enable_if<std::is_integral<int>::value, int>::type addT<int>(int value)
{
return value + 10;
}
#endif
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type addT(T value)
{
return value + 5.0;
}
/* First instantiated from: insights.cpp:21 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
typename std::enable_if<std::is_floating_point<double>::value, double>::type addT<double>(double value)
{
return value + 5.0;
}
#endif
int main()
{
int d = 10;
double f = 20;
d = addT(d);
f = addT(f);
return 0;
}
模版类特化:
#include <type_traits>
#include <iostream>
template <typename T, typename Enable = void>
class MyTestClass
{
// 默认实现,适用于所有类型
public:
MyTestClass() {
std::cout << "default";
}
};
template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_integral<T>::value>::type>
{
// 整型类型的特化实现
public:
MyTestClass() {
std::cout << "int";
}
};
template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{
// 浮点型类型的特化实现
public:
MyTestClass() {
std::cout << "float";
}
};
int main()
{
MyTestClass<std::string> x1;// OK :匹配初等模板
MyTestClass<int> x2; // OK :匹配偏特化 int
MyTestClass<double> x3; // OK :匹配偏特化 double
return 0;
}
模版展开后代码如下:
#include <type_traits>
#include <iostream>
template<typename T, typename Enable = void>
class MyTestClass
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "default");
}
};
/* First instantiated from: insights.cpp:35 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyTestClass<std::basic_string<char>, void>
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "default");
}
};
#endif
/* First instantiated from: insights.cpp:36 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyTestClass<int, void>
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "int");
}
};
#endif
/* First instantiated from: insights.cpp:37 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class MyTestClass<double, void>
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "float");
}
};
#endif
template<typename T>
class MyTestClass<T, typename std::enable_if<std::is_integral<T>::value>::type>
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "int");
}
};
template<typename T>
class MyTestClass<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{
public:
inline MyTestClass()
{
std::operator<<(std::cout, "float");
}
};
int main()
{
MyTestClass<std::basic_string<char>, void> x1 = MyTestClass<std::basic_string<char>, void>();
MyTestClass<int, void> x2 = MyTestClass<int, void>();
MyTestClass<double, void> x3 = MyTestClass<double, void>();
return 0;
}
参考文档:
https://cplusplus.com/reference/type_traits/is_integral/
std::enable_if - cppreference.com