2016-04-14 119 views
1

我不太明白下面的代碼,有兩個參數爲模板,第二個有class = xxxx,這對我來說似乎很奇怪。你能解釋一下我應該怎麼理解它?除std::enable_if之外,還有其他的用例,對於這個C++ 特性模板參數與默認值爲類

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 
bool is_even (T i) {return !bool(i%2);} 
+0

這是一個沒有名稱的默認模板參數。主要的「其他用例」在構造函數模板中,因爲構造函數沒有返回類型。 –

回答

2

一個字:SFINAE。

替換失敗不是錯誤。

用谷歌尋找這個詞,一個全新的世界將爲你打開。

讓我們看看你的代碼的含義。

std::is_integral<typename T>::value 

這是一個布爾值,從依賴型T與價值true如果T是整體式,false否則。

std::enable_if<bool B, typename T = void>::type 

這是T類型,當B == true,沒有其他。

所以,在代碼

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 

T是一個整體式,所述第二(未命名)模板參數取代有一個類型(默認:void;但是,在此情況下,確切類型是無關緊要的)並且該功能被激活。相反,當T不是整數類型時,代替第二個模板參數失敗,並且此版本的is_even()函數未激活(對於類型T),並且這是重要的一點,它不是錯誤(可以激活is_even()的另一個版本)。

更有趣的是可以看到如何爲非整數類型實現is_even()的替代版本。你可以認爲你可以實現否定std::is_integral

template < class T, 
class = typename std::enable_if<false == std::is_integral<T>::value>::type> 

但這不起作用另一個版本(是錯誤的,不編譯),因爲你有不同(從參數指向模板2個is_even()模板函數)僅適用於默認參數。

一個解決方案可以適用於SFINAE返回值

#include <type_traits> 
#include <iostream> 

template <typename T> 
typename std::enable_if<true == std::is_integral<T>::value, bool>::type 
is_even (T const & i) 
{ return ! (i%2); } 

template <typename T> 
typename std::enable_if<false == std::is_integral<T>::value, bool>::type 
is_even (T const &) 
{ return false; } 


int main() 
{ 
    std::cout << "-- is 7 even ?  " << is_even(7) << '\n'; 
    std::cout << "-- is 8UL even ? " << is_even(8LL) << '\n'; 
    std::cout << "-- is \"abc\" even ? " << is_even("abc") << '\n'; 

    return 0; 
} 

這樣你有整體式和第二版本的非整數類型(即回報甚至false)啓用了版本的is_even()

p.s .:抱歉我的英語不好。