Reputation: 73
Say I have following code
#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;
}
Is there a possibility (i.e. does the STL offer a construct) to lump together the two specialized cases calcFac<0>
and calcFac<1>
, so that I need only one function for both cases?
I.e.: calcFac</*if this parameter is 0 or 1 use that template function*/>
Upvotes: 1
Views: 76
Reputation: 70516
In soon-to-be-standardized C++1z, you can use if constexpr
template<int N>
auto calcFac() {
if constexpr (N > 1) {
return N * calcFac<N-1>();
}
return 1;
}
Upvotes: 0
Reputation: 2222
Edit:
My original design is flawed (doesn't work correctly with calcFac<0>()
). I take the design from @xaxxon instead. Saving my original design needs declaring three functions, but it does lump together the two specialised cases. You can find it at the very end of this answer.
There is, by using SFINAE and 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>();
}
How does this work:
std::enable_if_t<exp, Type>
is equivalent to Type
if exp
is true
, and undeclared otherwise. By using std::enable_if_t
this way in return type, will cause a SFINAE error when exp
is false
, thus the function is out of candidate list.
#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);
}
Upvotes: 3