Reputation: 9538
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
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
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
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
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
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