我不太明白下面的代碼,有兩個參數爲模板,第二個有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);}
我不太明白下面的代碼,有兩個參數爲模板,第二個有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);}
一個字: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 .:抱歉我的英語不好。
這是一個沒有名稱的默認模板參數。主要的「其他用例」在構造函數模板中,因爲構造函數沒有返回類型。 –