这里我定义了一个类模板Foo,专门化它的成员函数,然后为该类提供部分特化:
// 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";
}
};
我在VS2015上实例化了这样的Foo:
Foo<double, int> f;
f();
令人惊讶的是,f()打印&#34; Foo_0&#34;,这意味着不选择部分专用模板Foo_1。 什么甚至更奇怪,当我评论Foo :: bar(double)的特化时,f()打印&#34; Foo_1&#34;!
然后我测试一下:
Foo<int, int> f;
f();
这一次,f()还打印&#34; Foo_1&#34;,应用了类专业化。
因此,成员bar()的特化似乎会影响类模板的部分特化的应用。真的吗?为什么它会像这样工作?
答案 0 :(得分:3)
<div class="w-100"></div>
Foo<double, int>::bar
导致隐式实例化template<>
template<>
void Foo<double, int>::bar(double) {
std::cout << "Now I'm specialized!\n";
}
。这是比部分专业Foo<double, int>
更好的匹配,因此除非您注释掉Foo<T, int>
的特化,否则您将获得Foo_0
而不是Foo_1
。
您可以做的是将bar
作为常规重载成员函数移动到通用类模板bar(double)
Foo<T, S>
现在您将获得template<class T, class S>
class Foo {
// as before
void bar(double) {
std::cout << "Now I'm overloaded!\n";
}
};
,live example。请注意,您将无法再拨打Foo_1
。如果您需要,那么您还需要将Foo<double, int>::bar(double)
成员添加到部分特化bar
。