(I'm assuming knowledge of the Abrahams/Dimov example in this question.)
Assume there is some 3rd-party code in a header that like this, which you cannot modify:
template<class T> void f(T); // (1) base template 1
template<class T> void f(T *); // (2) base template 2
template<> void f<>(int *); // (3) specialization of (2)
The question is:
If I have been given the declarations above as-is, is it possible for me to now specialize the base template 1 for the case where T = int *
(for example)?
Or does the mere declaration of base template 2 imply that base template 1 can no longer be specialized (at least for pointers)?
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type. In C++ this can be achieved using template parameters.
This is title is from the C++ Core Guidelines: T.144: Don’t specialize function templates The reason for the rules is quite short: function template specialization doesn't participate in overloading. Let's see what that means. My program is based on the program snippet from Dimov/ Abrahams.
A function template can only be fully specialized, but because function templates can overload we can get nearly the same effect via overloading that we could have got via partial specialization. The following code illustrates these differences: template<class T> class X<T*> { /*...*/ }; template<> class X<int> { /*...*/ };
If that base template happens to be specialized for the types being used, the specialization will get used, otherwise the base template instantiated with the correct types will be used. Else if there's a tie for the "most specialized" function base template, the call is ambiguous because the compiler can't decide which is a better match.
In standardese, a full specialization is called an "explicit specialization." 2. There is some discussion going on within the committee about potentially allowing function template partial specialization in the next version of the C++ standard, whose work is just getting under way.
You can overload (1) by explicitly specifying the template parameter in the angle-brackets after the function name (cf. C++11-Standard 14.7.3)
#include <iostream>
using namespace std;
template<class T> void f(T) // (1) base template 1
{
cout << "template<class T> void f(T)" << endl;
}
template<class T> void f(T *) // (2) base template 2
{
cout << "template<class T> void f(T *)" << endl;
}
//template<> void f<>(int *); // (3) specialization of (2)
template<> void f<int*>(int *) // (4) specialization of (1)
{
cout << "f<int*>(int *)" << endl;
}
int main() {
int i;
f(&i); // calls (2) since only base-templates take part in overload resolution
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With