FloriHe
FloriHe

Reputation: 73

Put together template specializations

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

Answers (2)

TemplateRex
TemplateRex

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;
}

Live Example

Upvotes: 0

felix
felix

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

Related Questions