2017-02-16 10 views
1

Скажем, у меня есть следующий кодСколотить специализаций шаблона

#include <iostream> 

template<int N> 
int calcFac() { 

    return N*calcFac<N-1>(); 
} 

template<> 
int calcFac<1>() { 

    return 1; 
} 

template<> 
int calcFac<0>() { 

    return 1; 
} 

int main() { 

    int f4 = calcFac<4>(); 
    int f5 = calcFac<5>(); 
    int f1 = calcFac<1>(); 
    int f0 = calcFac<0>(); 

    std::cout <<"4! = "<<f4<<std::endl; 
    std::cout <<"5! = "<<f5<<std::endl; 
    std::cout <<"1! = "<<f1<<std::endl; 
    std::cout <<"0! = "<<f0<<std::endl; 

    return 0; 
} 

Есть ли возможность (то есть ли СТЛ предложение конструкт) сваливать вместе два специализированных случаях calcFac<0> и calcFac<1>, так что мне нужно только одну функцию для обоих случаев?

т.е .: calcFac</*if this parameter is 0 or 1 use that template function*/>

ответ

3

Edit: Мой оригинальный дизайн недостатки (не корректно работает с calcFac<0>()). Вместо этого я беру дизайн из @xaxxon. Сохранение моего первоначального дизайна требует объявления трех функций, но он объединяет два специализированных случая. Вы можете найти его в самом конце этого ответа.

Существует, с помощью SFINAE и std::enable_if_t

#include <type_traits> 
template <int N> 
std::enable_if_t<N <= 1, int> calcFac() { 
    return 1; 
} 

template<int N> 
std::enable_if_t<!(N <= 1), int> calcFac() { 
    return N*calcFac<N-1>(); 
} 

Как это работает:

std::enable_if_t<exp, Type> эквивалентно Type если exp является true и необъявленная иначе. Используя этот способ в обратном типе, вызовет ошибку SFINAE, если exp - false, поэтому функция не входит в список кандидатов.


#include <type_traits> 
template <int N> 
std::enable_if_t<N<=1, int> calcFacImpl(int) { 
    return 1; 
} 

template <int N> 
int calcFacImpl(...) { 
    return N*calcFacImpl<N-1>(0); 
} 

template <int N> 
int calcFac() { 
    return calcFacImpl<N>(0); 
} 
+0

Это выглядит хорошо – FloriHe

+2

это странно ввести неиспользуемый параметр, как это, хотя. Что-то вроде этого: https://godbolt.org/g/epF0wQ кажется мне более понятным. Хотя я, вероятно, сделаю это, если структуры не будут работать в первую очередь. Что-то больше похоже: https://godbolt.org/g/PB0Agq – xaxxon

+0

Я не уверен, что «ошибка SFINAE» - правильный термин. Если вы это произнесете, это звучит немного странно: сбой замены не является ошибкой ошибки ... – user463035818

0

В ближайшее время, чтобы быть стандартизированная C++ 1Z, вы можете использовать if constexpr

template<int N> 
auto calcFac() { 
    if constexpr (N > 1) { 
     return N * calcFac<N-1>(); 
    } 
    return 1; 
} 

Live Example