C++之std::enable_if的實(shí)現(xiàn)示例
1.概述
std::enable_if是C++11引入的模板結(jié)構(gòu)體,在VS2019中<xtr1common>文件定義,它的原型是:
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沒有定義,這種情況在程序編譯的時候就會報錯,此元函數(shù)是活用 SFINAE ,基于類型特性條件性地從重載決議移除函數(shù),并對不同類型特性提供分離的函數(shù)重載與特化的便利方法。 std::enable_if 可用作額外的函數(shù)參數(shù)(不可應(yīng)用于運(yùn)算符重載)、返回類型(不可應(yīng)用于構(gòu)造函數(shù)與析構(gòu)函數(shù)),或類模板或函數(shù)模板形參。
因此std::enable_if可以以多種形式使用,它的作用主要有:
1)通過函數(shù)的返回值,控制不同的條件下,選擇不同的模板
2)通過函數(shù)的參數(shù),控制不同的條件下,選擇不同的模板
3)作為類模板或函數(shù)模板參數(shù),控制不同的數(shù)據(jù)類型,選擇不同的類模板或函數(shù)模板
下面就舉例一一用示例說明它們的具體用法
2.函數(shù)返回值場景
#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;
}3.函數(shù)參數(shù)場景
示例1:
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;
}
示例2:
#include <iostream>
// enabled via a parameter
template<class T>
void destroy(T *,
typename std::enable_if<std::is_trivially_destructible<T>::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_trivially_destructible<T>{} &&
(std::is_class<T>{} || std::is_union<T>{}),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把數(shù)字或字符串轉(zhuǎn)換為std::string, 根據(jù)格式化的不同,就用std::enable_if控制調(diào)用不同的轉(zhuǎn)換函數(shù),代碼如下:
//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<std::is_same_v<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<std::is_same_v<T, const char*> ||
std::is_same_v<T, char*> ||
std::is_same_v<T, std::string>, T>* = 0) {
return value;
}
//4
template <typename T>
std::string tToString(T value, typename std::enable_if_t<std::is_integral_v<T> &&
!std::is_same_v <T, bool>, T>* = 0) { //std::is_integral_v<T>, 整數(shù)
char format[64] = { 0 };
sprintf(format, "%d", value);
return format;
}
//5
template <typename T>
std::string tToString(T value, typename std::enable_if_t<std::is_floating_point_v<T>, T>* = 0) { //浮點(diǎn)數(shù)
char format[64] = { 0 };
sprintf(format, "%f", value);
return format;
}
int main()
{
std::string f = tToString(true); //調(diào)用 2 版本函數(shù)
f = tToString(100); //調(diào)用 4 版本函數(shù)
f = tToString("43634636"); //調(diào)用 3 版本函數(shù)
f = tToString(88.4444); //調(diào)用 5 版本函數(shù)
f = tToString(std::string("435236236")); //調(diào)用 3 版本函數(shù)
char testT[] = "35353535345";
f = tToString(testT); //調(diào)用 1 版本函數(shù)
char* pTest = testT;
f = tToString(pTest); //調(diào)用 3 版本函數(shù)
const char* pTest1 = "ntrnrtnr44";
f = tToString(pTest1); //調(diào)用 3 版本函數(shù)
return 0;
}4.作為類模板或函數(shù)模板參數(shù)
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral_v<Integer>, int> = 0
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
std::enable_if_t<std::is_floating_point_v<Floating>, int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};template <typename T, typename Enable = void>
class MyTestClass
{
// 默認(rèn)實(shí)現(xiàn),適用于所有類型
public:
MyTestClass() {
std::cout << "default";
}
};
template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_integral<T>::value>::type>
{
// 整型類型的特化實(shí)現(xiàn)
public:
MyTestClass() {
std::cout << "int";
}
};
template <typename T>
class MyTestClass<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{
// 浮點(diǎn)型類型的特化實(shí)現(xiàn)
public:
MyTestClass() {
std::cout << "float";
}
};
int main()
{
MyTestClass<std::string> x1;// OK :匹配初等模板
MyTestClass<int> x2; // OK :匹配偏特化 int
MyTestClass<double> x3; // OK :匹配偏特化 double
return 0;
}參考
std::enable_if - cppreference.com
到此這篇關(guān)于C++之std::enable_if的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C++ std::enable_if內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++/類與對象/默認(rèn)成員函數(shù)@構(gòu)造函數(shù)的用法
這篇文章主要介紹了C++/類與對象/默認(rèn)成員函數(shù)@構(gòu)造函數(shù)的用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
VTK8.1?在?Qt5.9?環(huán)境下的配置編譯和安裝過程
為了實(shí)現(xiàn)realsense的PCL點(diǎn)云顯示,需要VTK支持。由于整個平臺在Qt環(huán)境實(shí)現(xiàn),VTK編譯為Qt插件。整個過程并不復(fù)雜,網(wǎng)上的文章大多不全,自己梳理了一下,分享出來,需要的朋友可以參考下2022-07-07

