Question

I'm on a roll today. Here goes n00b question number 7:

What's the difference between explicit specialization and just regular functions when you try to overload a template function?

What's the appropriate situation to use the explicit specialization? I don't quite understand it:

#include <iostream>

template <typename s> void test(s var1);
template <> void test<int>(int var1);

int main(){
    test(1);
    test(1.1);
    test("hello!!");
    return 0;
}

template <typename s> void test(s var1){
    std::cout << var1 << std::endl;
}

template <> void test<int>(int var1){
    std::cout << "int " << var1 << std::endl;
}

As oppose to:

#include <iostream>

template <typename s> void test(s var1);
void test(int var1);

int main(){
    test(1);
    test(1.1);
    test("hello!!");
    return 0;
}

template <typename s> void test(s var1){
    std::cout << var1 << std::endl;
}

void test(int var1){
    std::cout << "int " << var1 << std::endl;
}
Was it helpful?

Solution

There really isn't a difference between an explicitly specialized template function and a non-template regular function other than the fact that when the compiler looks for a matching signature type for the function call, it will first pick a non-template function that matches the required signature before trying to instantiating any available template functions that may fulfill the required signature match.

If you are going to declare and define a function inside a header file that is not a template-function though, you will have to declare the function as inline. That is because a template function is not an actual function that is linked with a code module until it is actually instantiated. The linker then throws away that instantiation after compiling the code module. If the linker did not do this, then every time a .cpp file included the header file, the linker would complain about duplicate definitions for a function. Using the inline keyword on a non-template function has a similar effect at the compiler level, in that any time the function is used in a .cpp file, the compiler replaces that function call with the body of the function code from the inline function in the header file, and avoids the overhead of a function call with an associated stack active record setup and clean-up. Therefore the linker won't complain about duplicate definitions for a function.

OTHER TIPS

I'm not an expert, but my experience is to use templates (and specialization) when I want to define different return types. You can't overload the return type of a function.

A major difference is: Explicit specializations don't participate in overloading at all.

template<typename T> void f(T const&);
template<> void f<char const*>(char const * const&);

Calling with f("hello") will not consider any explicit specializations. It will only take all templates, and deduce their template arguments. The above T will be deduced to char[6], and so the specialization won't be selected.

If you overload the function template instead, you have completely different characteristics.

template<typename T> void f(T const&);
void f(char const * const&);

Calling this, it will select the second function, because both the (char const(&)[6]) parameter of the generated specialization and the (char const * const&) parameter match the argument equally well, but the second function is a non-template function, hence it is preferred eventually.

When the compiler comes across a function call, it first looks for a non-template function definiton, then an explicitly specialized template and finally, a template definition whose signature matches with the function call. So, for example, if you have an explicitly defined template and a template, then the complier goes for the explicitly defined template. Therefore, you should use an explicity specialzed template when you want to handle a particular datatype in a different manner from the way the template would have handled it.

Another use for explicit specialization is when you want to "overload" a function that does not take any arguments. You can use explicit specialization to give different definitions to the function to handle different datatypes.

IMHO, explicit specialization for function template should be used when, you are going to call that function using explicit template argument. e.g.

test<int>(myClass); // no argument for 'int' -> declare test() as template specialization

In other cases, you should always use normal specialization. e.g.

test(10, myClass); // argument 10 is 'int' -> test() should be normal specialized

Technically there is no difference between normal and explicit template specialization of a function. The normal specialized versions are completely independent of template functions.

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