相关系列文章
目录
1.概述
std::enable_if是C++11引入的模板结构体,在VS2019中
- template <bool _Test, class _Ty = void>
- struct enable_if {}; // no member "type" when !_Test
-
- template <class _Ty>
- struct enable_if<true, _Ty> { // type is _Ty for _Test
- using type = _Ty;
- };
-
- template <bool _Test, class _Ty = void>
- using enable_if_t = typename enable_if<_Test, _Ty>::type;
_Test如果是true, std::enable_if的type为_Ty;如果是false, type没有定义,这种情况在程序编译的时候就会报错,此元函数是活用 SFINAE ,基于类型特性条件性地从重载决议移除函数,并对不同类型特性提供分离的函数重载与特化的便利方法。 std::enable_if 可用作额外的函数参数(不可应用于运算符重载)、返回类型(不可应用于构造函数与析构函数),或类模板或函数模板形参。
因此std::enable_if可以以多种形式使用,它的作用主要有:
1)通过函数的返回值,控制不同的条件下,选择不同的模板
2)通过函数的参数,控制不同的条件下,选择不同的模板
3)作为类模板或函数模板参数,控制不同的数据类型,选择不同的类模板或函数模板
下面就举例一一用示例说明它们的具体用法
2.函数返回值场景
- #include
- #include
-
- template <typename T>
- typename std::enable_if
::value, T>::type addT(T value) - {
- return value + 10;
- }
-
- template <typename T>
- typename std::enable_if
::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;
- }
3.函数参数场景
示例1:
- template <typename T>
- T addT(T value, typename std::enable_if
::value, T>::type* = nullptr) - {
- return value + 10;
- }
-
- template <typename T>
- T addT(T value, typename std::enable_if
::value, T>::type* = nullptr) - {
- return value + 5;
- }
-
- int main()
- {
- int d = 10;
- double f = 20;
- d = addT(d);
- f = addT(f);
- return 0;
- }
示例2:
- #include
-
- // enabled via a parameter
- template<class T>
- void destroy(T *,
- typename std::enable_if
::value>::type * = 0) { - std::cout << "destroying trivially destructible T\n";
- }
-
- // enabled via a non-type template parameter
- template<class T, typename std::enable_if{} &&
- (std::is_class
{} || std::is_union{}),bool>::type = true> - void destroy(T* t)
- {
- std::cout << "destroying non-trivially destructible T\n";
- }
-
- int main() {
- int nValue = 1;
- std::string test = "hell";
- destroy(&nValue);
- destroy(&test);
- return 0;
- }
-
- 输出如下:
- destroying trivially destructible T
- destroying non-trivially destructible T
示例3:
利用sprintf把数字或字符串转换为std::string, 根据格式化的不同,就用std::enable_if控制调用不同的转换函数,代码如下:
- //1
- template <int N>
- std::string tToString(char(&value)[N])
- {
- std::string temp;
- for (int i = 0; i < N; i++) {
- temp += value[i];
- }
- return temp;
- }
- //2
- template <typename T>
- std::string tToString(T value, typename std::enable_if_t
bool >, T>* = 0) { - char format[64] = { 0 };
- sprintf(format, "%s", value ? "true" : "false");
- return format;
- }
- //3
- template <typename T>
- std::string tToString(T value, typename std::enable_if_t
const char*> || - std::is_same_v
char *> || - std::is_same_v
, T>* = 0) { - return value;
- }
- //4
- template <typename T>
- std::string tToString(T value, typename std::enable_if_t
&& - !std::is_same_v
bool >, T>* = 0) { //std::is_integral_v, 整数 - char format[64] = { 0 };
- sprintf(format, "%d", value);
- return format;
- }
- //5
- template <typename T>
- std::string tToString(T value, typename std::enable_if_t
, T>* = 0) { //浮点数 - char format[64] = { 0 };
- sprintf(format, "%f", value);
- return format;
- }
- int main()
- {
- std::string f = tToString(true); //调用 2 版本函数
- f = tToString(100); //调用 4 版本函数
- f = tToString("43634636"); //调用 3 版本函数
- f = tToString(88.4444); //调用 5 版本函数
- f = tToString(std::string("435236236")); //调用 3 版本函数
-
- char testT[] = "35353535345";
- f = tToString(testT); //调用 1 版本函数
-
- char* pTest = testT;
- f = tToString(pTest); //调用 3 版本函数
-
- const char* pTest1 = "ntrnrtnr44";
- f = tToString(pTest1); //调用 3 版本函数
-
- return 0;
- }
4.作为类模板或函数模板参数
- struct T {
- enum { int_t,float_t } m_type;
- template <typename Integer,
- std::enable_if_t
, int> = 0 - >
- T(Integer) : m_type(int_t) {}
-
- template <typename Floating,
- std::enable_if_t
, int> = 0 - >
- T(Floating) : m_type(float_t) {} // OK
- };
- template <typename T, typename Enable = void>
- class MyTestClass
- {
- // 默认实现,适用于所有类型
- public:
- MyTestClass() {
- std::cout << "default";
- }
- };
-
- template <typename T>
- class MyTestClass
typename std::enable_if::value>::type> - {
- // 整型类型的特化实现
- public:
- MyTestClass() {
- std::cout << "int";
- }
- };
-
- template <typename T>
- class MyTestClass
typename std::enable_if::value>::type> - {
- // 浮点型类型的特化实现
- public:
- MyTestClass() {
- std::cout << "float";
- }
- };
- int main()
- {
- MyTestClass
x1;// OK :匹配初等模板 - MyTestClass<int> x2; // OK :匹配偏特化 int
- MyTestClass<double> x3; // OK :匹配偏特化 double
- return 0;
- }
参考
评论记录:
回复评论: