Question

I have a function of the form

template<int a, int b>
void f();

That I'd like to specialize when a == b. Pseudocode looks something like:

template<int a>
void f<a, a>(){ //something}

template<int a, int b>
void f<a, b>(){ //something different}

Is this possible without partial template specialization issues?

Edit: Thanks for the quick reply. The method is actually inside of a class, more like this:

<typename a> class A{ 
    template<int b, int c> f(); 
}; 

A inst; 
inst.f<1,1>(); 
inst.f<1,2>(); 
Was it helpful?

Solution

You cannot partially specialize a function template, but you can partially specialize a class template.

This leaves room for the following trick, where the actual work is being done by static member functions of a primary function template and a specialized function template, to which your original f() function delegates its responsibility:

#include <iostream>

namespace detail
{
    template<int A, int B>
    struct helper
    {
        static void call() { std::cout << "f<A, B>()" << std::endl; }
    };

    template<int A>
    struct helper<A, A>
    {
        static void call() { std::cout << "f<A, A>()" << std::endl; }
    };
}

template<int a, int b>
void f()
{
    detail::helper<a, b>::call();
}

This is how you could use your f() function template:

int main()
{
    f<1, 2>();
    f<1, 1>();
}

Here is a live example.

EDIT:

If your function template is a member function, things get slightly more complicated, but the solution outlined above for turning function template partial specialization into class template partial specialization is still viable.

This is how you would go about it based on the example provided in the comments.

First, forward-declare the helper class template and grant its instantiations the right to access your class template A's private members (the role of the additional type parameter T will become clear in a moment):

namespace detail
{
    template<typename T, int A, int B>
    struct helper;
}

template <typename a>
class A
{
public:
    template<int b, int c>
    void f();
private:
    template<typename, int, int> friend struct detail::helper;
};

Then you would define the helper class template and its specialization as done before, but adding a function parameter to the call() functions of the type necessary to manipulate the class object on which the original member function f() has been invoked:

namespace detail
{
    template<typename T, int A, int B>
    struct helper
    {
        static void call(T* p) { std::cout << "f<A, B>()" << std::endl; }
    };

    template<typename T, int A>
    struct helper<T, A, A>
    {
        static void call(T* p) { std::cout << "f<A, A>()" << std::endl; }
    };
}

Then you could define the member function f() as shown below:

template<typename a>
template<int b, int c>
void A<a>::f()
{
    detail::helper<A<a>, b, c>::call(this);
}

And eventually use it this way:

int main()
{
    A<int> inst;
    inst.f<1,1>();
    inst.f<1,2>();
}

This is all put together in this live example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top