模版偏特化之std::enable_if

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);通过如下网站可以展开上面代码

C++ Insights

#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

C++之std::enable_if_std enable if-CSDN博客

C++模板编程 | `std::enable_if` 和 SFINAE_模板类 std::enable-CSDN博客

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值