2016-04-14 4 views
1

Я не совсем понимаю ниже код, есть два параметра для шаблона, второй - class = xxxx. Мне это кажется странным. Не могли бы вы объяснить мне, как я должен это понимать? и кроме того std::enable_if, есть ли другой прецедент для этого C++ feature?параметр шаблона со значением по умолчанию для класса

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.

Замена Ошибка не является ошибкой.

Ищите это слово с Google и откроете для вас новый мир.

Посмотрите на смысл своего кода.

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> 

, но это не работает (ошибка и не компилировать), потому что у вас есть два 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; 
} 

Таким образом, у вас есть версия is_even() включена для интегрального типа и второй версии (возвращающих даже false) для не целочисленных типов.

p.s .: извините за мой плохой английский.

Смежные вопросы