std::enable_if的用法

一、測試程序1

#include <iostream>
#include <type_traits>
using namespace std; 

template <typename T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
gt_zero (T i) { 
    cout << "is integral" << endl;
    return i>0;  
}
template <typename T>
typename std::enable_if<!std::is_integral<T>::value,bool>::type
gt_zero (T i) { 
    cout << "is NOT integral" << endl;
    return i>0; 
}

int main() {
  short int i = 2;    
  float f = 3.1;
  std::cout << i << " greater than zero : " << gt_zero(i) << std::endl;
  std::cout << f << " greater than zero : " << gt_zero(f) << std::endl;
  return 0;
}

首先gt_zero是一個模板函數,typename std::enable_if<std::is_integral<T>::value,bool>::type是函數的返回值類型,std::enable_if<>一般是由兩部分組成,第一個參數是一個判定式,當判定式爲真時,std::enable_if<std::is_integral<T>::value,bool>::type的這個type數據成員存在,且值爲bool,如果沒有第二個參數,則默認值爲void。如果判定式爲假,type這個數據成員就是未定義的,更不存在值是什麼。

但是編譯器並不會因爲type值不存在就報錯,因爲泛型編程中存在一個最優匹配原則,這個模板不成立,就去推斷其他模板,所以gt_zero實際上同時是一個重載函數。

當第一個參數std::is_integral<T>::value爲假時,!std::is_integral<T>::value肯定爲真,所以第二個模板函數符合要求,同樣std::enable_if<std::is_integral<T>::value,bool>::type的值爲true。

 執行結果:

is integral
1 greater than zero : 1
is NOT integral
3.1 greater than zero : 1

根據上文分析可以得到兩次調用gt_zero函數第一次調用是第一個版本,第二次調用是第二個版本。 

二、測試程序2

#include <iostream>
#include <type_traits>
using namespace std; 

template <typename T>
bool
gt_zero (T i, typename std::enable_if<std::is_integral<T>::value, T>::type j=0) { 
    cout << "is integral" << endl;
    return i>0;  
}
template <typename T>
bool
gt_zero (T i, typename std::enable_if<!std::is_integral<T>::value,T>::type j=0) { 
    cout << "is NOT integral" << endl;
    return i>0; 
}

int main() {
  short int i = 2;    
  float f = 3.1;
  std::cout << i << " greater than zero : " << gt_zero(i) << std::endl;
  std::cout << f << " greater than zero : " << gt_zero(f) << std::endl;
  return 0;
}

有了第一個程序的鋪墊,第二個測試程序就簡單許多了。首先gt_zero函數的返回值類型已經被指定爲bool類型了,gt_zero函數的第二個參數typename std::enable_if<std::is_integral<T>::value, T>::type j=0表明定義了一個j變量,但是type同樣是在std::is_integral<T>::value成立的條件下才會有定義,成立時type的值是T,定義j這個變量大多時候的作用只是限制函數接收數據類型的種類,重載模板函數使得模板函數可以根據不同的數據類型執行不同的函數。 

 執行結果:

is integral
2 greater than zero : 1
is NOT integral
3.1 greater than zero : 1

三、測試程序3

#include <iostream>
#include <type_traits>
using namespace std; 

template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
bool
gt_zero (T i) { 
    cout << "is integral" << endl;
    return i>0;  
}
template <typename T, typename std::enable_if<!std::is_integral<T>::value>::type* = nullptr>
bool
gt_zero (T i) { 
    cout << "is NOT integral" << endl;
    return i>0; 
}

int main() {
  short int i = 2;    
  float f = 3.1;
  std::cout << i << " greater than zero : " << gt_zero(i) << std::endl;
  std::cout << f << " greater than zero : " << gt_zero(f) << std::endl;
  return 0;
}

執行結果:

is integral
2 greater than zero : 1
is NOT integral
3.1 greater than zero : 1

四、std::is_integral

函數原型:template< class T > struct is_integral;
功能:檢查 T 是否爲整數類型。若 T 爲 bool 、 char 、 char8_t 、 char16_t 、 char32_t 、wchar_t 、 short 、 int 、 long 、 
long long 類型,或任何實現定義的擴展整數類型,包含任何有符號、無符號及 cv 限定的變體。則提供等於 true 的成員常量 value 。
否則, value等於 false 。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章