Here I define a class template Foo, specialize its member function, and then supply a partial specialization for that class:
// this is Foo_0
template<typename T, typename S>
class Foo {
public:
void operator()() {
std::cout << "Foo_0\n";
}
template<typename R>
void bar(R) {
std::cout << "I'm from Foo_0\n";
}
};
template<>
template<>
void Foo<double, int>::bar(double) {
std::cout << "Now I'm specialized!\n";
}
// this is Foo_1
template<typename T>
class Foo<T, int> {
public:
void operator()() {
std::cout << "Foo_1\n";
}
};
And I instantiate Foo on VS2015 like this:
Foo<double, int> f;
f();
Surprisingly, f() prints "Foo_0", which means the partial specialized template Foo_1 isn't chosen. What's even stranger, when I comment the specialization of Foo::bar(double), f() prints "Foo_1"!
Then I test this:
Foo<int, int> f;
f();
This time, f() also prints "Foo_1", the class specialization is applied.
So it seems that the specialization of member bar() do influence the application of partial specialization of the class template. Is that true? Why does it work like this?
The explicit specialization of Foo<double, int>::bar
template<>
template<>
void Foo<double, int>::bar(double) {
std::cout << "Now I'm specialized!\n";
}
causes an implicit instantiation of Foo<double, int>
. This is a better match than the partially specialized Foo<T, int>
, so you get Foo_0
instead of Foo_1
, unless you comment out the specialization of bar
.
What you could do is to move bar(double)
into the general class template Foo<T, S>
as a regular overloaded member function
template<class T, class S>
class Foo {
// as before
void bar(double) {
std::cout << "Now I'm overloaded!\n";
}
};
Now you will get Foo_1
, live example. Note that you won't be able to call Foo<double, int>::bar(double)
anymore. If you want that, then you need to add a bar
member to the partial specialization Foo<T, int>
as well.