问题
I have class member functions defined as follows, providing a specification for one of them and letting the user provide their own specification for others:
template <typename T>
class Foo {
// specialization provided for integral types
template <typename Enable = T>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
bar(const T& value);
// provide your own specialization for other types
template <typename Enable = T>
typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
bar(const T& value);
};
template <typename T>
template <typename Enable>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
Foo<T>::bar(const T& value) {
...
}
Now, I'd like to provide a specialization for the function that will work for integral pair types. I have a template metafunction checking for integral pairs defined as follows:
template <typename T>
struct is_integral_pair : std::false_type {};
template <typename T1, typename T2>
struct is_integral_pair<std::pair<T1, T2>> {
static const bool value =
std::is_integral<T1>::value && std::is_integral<T2>::value;
};
Is it possible for me to provide my own specialization such that it works for all integer pairs, perhaps using the template metafunction I defined above?
回答1:
Its a bit of a contrived example and somewhat difficult to make sense of as-is. However, with a basic change its quite easy to add what you require. First its important to note that what you're defining above are not partial specialisations of bar
(that would be impossible as you cannot partially specialize a function) but rather overloads. Next, you have a contrived system whereby you have an Enable
parameter that has nothing to do with the function parameter - is this really your intention? If you made the change that the template parameter of the function is the same type as its variable parameter, the problem becomes straightforward - you add another overload for integral pairs, again using SFINAE to help you. Here is an example way of achieving what you need:
#include <iostream>
template <typename T>
class Foo {
public:
// specialization provided for integral types
template <typename Enable>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
bar(const Enable& value);
// provide your own specialization for other types
template <typename Enable>
typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
bar(const Enable& value);
// provide your own specialization for integral pairs
template <typename U, typename V>
typename std::enable_if<std::is_integral<U>::value && std::is_integral<V>::value, size_t>::type
bar(const std::pair<U,V>& value);
};
template <typename T>
template <typename Enable>
typename std::enable_if<std::is_integral<Enable>::value, size_t>::type
Foo<T>::bar(const Enable& value)
{
std::cout << "Integral" << std::endl;
return 0;
}
template <typename T>
template <typename Enable>
typename std::enable_if<!std::is_integral<Enable>::value, size_t>::type
Foo<T>::bar(const Enable& value)
{
std::cout << "Non-Integral" << std::endl;
return 0;
}
template <typename T>
template <typename U, typename V>
typename std::enable_if<std::is_integral<U>::value && std::is_integral<V>::value, size_t>::type
Foo<T>::bar(const std::pair<U,V>& value)
{
std::cout << "Integral pair" << std::endl;
return 0;
}
int main()
{
Foo<int> foo;
foo.bar(1); //output "Integral"
foo.bar(1.0); //output "Non-Integral"
foo.bar(std::pair<float, int>(1.0, 1)); //output "Non-integral"
foo.bar(std::pair<long, int>(1, 1)); //output "Integral pair"
return 0;
}
来源:https://stackoverflow.com/questions/38098372/template-partial-specialization-for-multiple-types-overriding-member-function