class 模板部分特化和 class 成员特化有些令人困惑
something confusing about class template partial specialization & class member specialization
这里我定义了一个 class 模板 Foo,特化了它的成员函数,然后为它提供了一个偏特化 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";
}
};
然后我在 VS2015 上实例化 Foo,如下所示:
Foo<double, int> f;
f();
令人惊讶的是,f() 打印 "Foo_0",这意味着未选择部分专用模板 Foo_1。
更奇怪的是,当我评论 Foo::bar(double) 的特化时,f() 打印 "Foo_1"!
然后我测试这个:
Foo<int, int> f;
f();
这一次,f() 还打印 "Foo_1",应用了 class 特化。
因此,成员 bar() 的特化似乎确实影响了 class 模板的部分特化的应用。真的吗?为什么会这样?
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)
作为常规重载成员函数移入通用 class 模板 Foo<T, S>
template<class T, class S>
class Foo {
// as before
void bar(double) {
std::cout << "Now I'm overloaded!\n";
}
};
现在您将获得Foo_1
、live example。请注意,您将无法再调用 Foo<double, int>::bar(double)
。如果你想要那样,那么你还需要向偏特化 Foo<T, int>
添加一个 bar
成员。
这里我定义了一个 class 模板 Foo,特化了它的成员函数,然后为它提供了一个偏特化 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";
}
};
然后我在 VS2015 上实例化 Foo,如下所示:
Foo<double, int> f;
f();
令人惊讶的是,f() 打印 "Foo_0",这意味着未选择部分专用模板 Foo_1。 更奇怪的是,当我评论 Foo::bar(double) 的特化时,f() 打印 "Foo_1"!
然后我测试这个:
Foo<int, int> f;
f();
这一次,f() 还打印 "Foo_1",应用了 class 特化。
因此,成员 bar() 的特化似乎确实影响了 class 模板的部分特化的应用。真的吗?为什么会这样?
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)
作为常规重载成员函数移入通用 class 模板 Foo<T, S>
template<class T, class S>
class Foo {
// as before
void bar(double) {
std::cout << "Now I'm overloaded!\n";
}
};
现在您将获得Foo_1
、live example。请注意,您将无法再调用 Foo<double, int>::bar(double)
。如果你想要那样,那么你还需要向偏特化 Foo<T, int>
添加一个 bar
成员。