2015-10-01 2 views
1

Я делаю простую функцию max, чтобы поэкспериментировать с метапрограммированием шаблонов в C++. Я ожидал увидеть «Интеграл» для отображения, когда я вызываю функцию с междунар, но это не так и я не знаю, почему:Шаблон метапрограмм интегральной специализации

#include <iostream> 

template<class... > struct make_void { typedef void type; }; 
template<class... Ts> using void_t = typename make_void<Ts...>::type; 

#include <type_traits> 

template < class T, class = void_t < typename std::is_integral<T>::value > > 
    T max(T x, T y) { 
    std::cout << "integral" << std::endl; 
    return x > y ? x : y; 
} 

template<class T, class = void> 
    T max(const T& x, const T& y) { 
    std::cout << "class" << std::endl; 
    return x > y ? x : y; 
} 

int main() { 
    int x = 5,y = 3; 
    std::cout << "int: "; 
    max(x,y); 
    struct str{bool operator>(const str&other)const{return true;}} a, b; 
    std::cout << "blank struct: "; 
    max(a,b); 
} 

В обоих случаях он печатает класс, который беспокоит меня, так как я думал, что SFINAE чаще выбирает лучший вариант. Я не понимаю, что происходит.

+0

Вы не имеете SFINAE здесь? –

+0

'std :: is_integral :: value' не является' типом'. – Jarod42

+0

Во-первых, избавиться от 'typename'. Далее, 'void_t' не является инструментом для использования здесь в этом контексте. Используйте 'std :: enable_if_t'. Вам также нужно отрицание условия ('! Is_integral') во второй перегрузке. http://coliru.stacked-crooked.com/a/2bdcf651c1e7604c – 0x499602D2

ответ

4

std::is_integral<T>::value не является типом, так

template < class T, class = void_t<typename std::is_integral<T>::value>> 
T max(T x, T y) 

по-прежнему отвергается с SFINAE.

Вы можете использовать std::enable_if_t

template<class T> 
std::enable_if_t<std::is_integral<T>::value, T> max(const T& x, const T& y) { 
    std::cout << "integral" << std::endl; 
    return x > y ? x : y; 
} 

template<class T> 
std::enable_if_t<!std::is_integral<T>::value, T> max(const T& x, const T& y) { 
    std::cout << "class" << std::endl; 
    return x > y ? x : y; 
} 

Demo

+0

Как это специализируется? – 0x499602D2

+0

Не могли бы вы рассказать о том, как заставить его работать по назначению? – Czipperz

+1

@ 0x499602D2: Действительно, он не является более специализированным. Ответ переписан. – Jarod42

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