Pwnna
Pwnna

Reputation: 9538

Difference between explicit specialization and regular functions when overloading a template function

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

Upvotes: 14

Views: 1488

Answers (5)

iambrj
iambrj

Reputation: 71

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.

Upvotes: 1

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506955

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.

Upvotes: 3

Stew
Stew

Reputation: 31

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.

Upvotes: 3

iammilind
iammilind

Reputation: 69988

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.

Upvotes: 0

Jason
Jason

Reputation: 32510

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.

Upvotes: 6

Related Questions