Question

I want to write the following:

template <typename S, typename T> void foo() {
    /* code for the general case */
}

template <typename T> void foo<MySType,T>() {
    /* partially specialized code - for any kind of T, but when S is MySType */
}

or, in other cases, the following:

template <typename S, typename T> void bar(const S& a, const T& b) {
    /* code for the general case */
}

template <typename T> void bar<MySType,T>(const MySType& a, const T& b) {
    /* partially specialized code - for any kind of T, but when S is MySType */
}

C++(11) won't let me do this.

Now, I read this question and its answers; let's assume I buy the explanation of why we don't have partial template specialization (or just assume that that I'm living in reality and actually want to write code). Well, what do I do, in stead?

I would really rather not wrap these functions in a class unless that's absolutely my last resort.

Was it helpful?

Solution 2

Another option is to use a helper class template, where you can do partial specialization, and hide it using a wrapper function which doesn't need to be partially specialized itself:

#include <iostream>

template<typename S, typename T>
struct foo_helper {
    void foo() {
        std::cout << "general func" << std::endl;        
    }
};

struct MyType {};

template <typename T>
struct foo_helper <MyType,T> {
    void foo() {   
        std::cout << "partially specialized code - for any kind of T, but when S is MyType" << std::endl;
    }
};

template<typename S, typename T>
void foo() {
    foo_helper<S, T>().foo();
}

int main () {
    foo<int, int>();
    foo<int, double>();
    foo<MyType, long>();
}

This is valid C++98/03 as well.

OTHER TIPS

Overload! Overloading is superior in every way to specialization. Part of overload resolution is picking the most specialized overload. Just declare the "specializations" as overloads and it will work if partial specialization would have.

Avoid explicit template arguments, though. You might use tag dispatching instead.

template< typename t >
struct tag {};

template <typename S, typename T> foo( tag<S>, tag<T> ) {
    /* code for the general case */
}

template <typename T> foo( tag<MyType>, tag<T> ) {
    /* partially specialized code - for any kind of T, but when S is MyType */
}

Since the tags are empty and passed by value, their contribution to function call overhead may be eliminated by the compiler.

You might partial specialize a helper structure:

#include <iostream>

namespace Detail {
    template <typename S, typename T>
    struct Foo {
        static void apply() {
            std::cout << "general case\n";
        }
    };
    template <typename T>
    struct Foo<int, T> {
        static void apply() {
            std::cout << "specialized code\n";
        }
    };
}

template <typename S, typename T>
void foo() {
    Detail::Foo<S, T>::apply();
}

int main()
{
    foo<double, double>();
    foo<int, double>();
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top