Question

How do I specialize a function template in c++?

#include <iostream>

template <int X = 0>  //Wrong attempt, does not compile.
int func(int y)
{
    return X + y;
}

template<int X>
int func(int y)
{
    return X + func<X-1>(y);
}


int main()
{
    std::cout << func<1>(2);
    return 0;
}

I would like the result of this program to be: 1 + 0 + y = 3.

For y = 2 it would be: 2 + 1 + 0 + y.

I know there are better ways to do this calculation, I am trying to understand this aspect of the language.

Was it helpful?

Solution

Overloads the function by delegating

template <int X>
class Int 
{
};

template <int X>
int funcSwitch(int y, Int<X>)
{
    return X + funcSwitch(y, Int<X-1>());
}

int funcSwitch(int y, Int<0>)
{
    return y;
}

template<int X>
int func(int y)
{
    return funcSwitch(y, Int<X>());
}

int main()
{
    std::cout << func<1>(2);
    return 0;
}

You need to be careful not to define Int in another namespace than funcSwitch, because then the call in the first funcSwitch would not find the second funcSwitch case when it is instantiated (this is because of a rule called ADL). To not think about this, you can also write a class template to delegate to

template<int X>
struct FuncImpl {
    int operator()(int y) const {
        return X + FuncImpl<X-1>()(y);
    }
};

template<>
struct FuncImpl<0> {
    int operator()(int y) const {
        return y;
    }
};

template<int X>
int func(int y)
{
    return FuncImpl<X>()(y);
}

int main()
{
    std::cout << func<1>(2);
    return 0;
}

In general I prefer the technique without a class, because it allows for member functions to still access *this and its private members if func were a member function.

To be complete, there is also "explicit specialization" for functions, but because of its limits and pitfalls, I would not recommend it. In this case it would work and would be

template<int X>
int func(int y)
{
    return X + func<X-1>(y);
}


template <>
int func<0>(int y)
{
    return y;
}

int main()
{
    std::cout << func<1>(2);
    return 0;
}

OTHER TIPS

The answer by Johannes Schaub - litb covers pretty much everything on overloading.

But you can also keep in mind that in some cases, some of the compile-time computations (especially involving scalars of integral types) may be carried out by constexpr functions, which are simpler than overloading. In your specific example, this applies:

constexpr int f(int x) { return x ? x + f(x-1) : 0; }

template<int x>
int func(int y) { return f(x) + y; }

separating the effect of x from the effect of y (recursion only refers to x).

In such case no template specialization is needed. You can simply write the following code using a formula for a sum of an arithmetic progression: 0 + 1 + 2 + ... + x = x * (x + 1) / 2.

template <int x>
int func(int y)
{
    return y + x * (x + 1) / 2;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top