问题描述:

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.

网友答案:

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.

相关阅读:
Top