Reputation: 4953
I've been looking at many other questions that talk about template specialization and I just can't seem to find the answer to my problem. I have read that you can't partially specialize function templates. So what would be a work around for the following.
Consider a function named type
. This function is meant to return a single char
denoting its type. As you build your classes you will have to "overload" or specialize the function type
so that a function named print_type
can print the type of the object without us having to call the function type
. Here is some code:
#include <cstdio>
#include <string>
#include <vector>
template<class T> inline char type(const T&) {return 'S';}
template<> inline char type(const int&) {return 'I';}
template<> inline char type(const double&) {return 'R';}
template<class T>
void print_type(T& t) {
printf("Type = %c\n", type(t));
}
// OTHER FUTURE TYPES
template<> inline char type(const std::string&) {return 'W';}
template<class T> inline char type(const std::vector<T>&) {return 'T';}
int main() {
int x;
printf("Int type: %c\n", type(x));
print_type(x);
double y;
printf("Double type: %c\n", type(y));
print_type(y);
std::string str;
printf("String type: %c\n", type(str));
print_type(str);
std::vector<int> vtor;
printf("Vector type: %c\n", type(vtor));
print_type(vtor);
}
Notice that I have define specialized type
for the std::string
. Somehow it seems that it isn't possible to do with std::vector<T>
of some type T
. The result of running the above code gives:
macbook-pro:~ jmlopez$ ./a.out
Int type: I
Type = I
Double type: R
Type = R
String type: W
Type = W
Vector type: T
Type = S
The print_type
function wasn't able to pick up the definition for std::vector<std::string>
and it simply default to original template function I defined. What would be a work around for this? Keep in mind that I must be able to define type
for some other unknown types in some possible future and thus I cannot declare the function print_type
after all the definitions of type
have been set.
Upvotes: 2
Views: 211
Reputation: 153792
The canonical work-around for not being able to partially specialize a function template is to delegate to partially specialized class templates, probably with suitable static
member functions. For example:
template <typename> struct type_aux { static char type() { return 'S'; } };
template <> struct type_aux<int> { static char type() { return 'I'; } };
template <> struct type_aux<double> { static char type() { return 'R'; } };
template <> struct type_aux<std::string> { static char type() { return 'W'; } };
template <typename T> struct type_aux<std::vector<T>> {
static char type() { return 'T'; }
}
template <typename T> char type(T const&) { return type_aux<T>::type(); }
Just to explain why your approach doesn't work the way you wrote it: the function template template <typename T> char type(std::vector<T> const&)
would need to be found during instantiation of print_type()
. However, at this point functions are only found with argument dependent look-up which won't go looking where you defined it. You could make your function template found if you'd declared it in namespace std
but you are not allowed to do so. The specialization approach entirely side-steps the problem of having to locate functions.
Upvotes: 2