我正在尝试编写一个具有部分和显式特化的类。虽然名字查找怪癖有问题。现在我有:
template <typename C, typename R>
class Command {
public:
Command();
private:
void doTheDew() {
/* ... */
}
};
template <typename C, typename R>
Command<C, R>::Command() {
doTheDew();
}
template<typename R>
class Command<void, R> {
public:
Command() {
this->doTheDew();
}
};
template<typename C>
class Command<C, void> {
public:
Command() {
this->doTheDew();
}
};
template<>
class Command<void, void> {
public:
Command() {
this->doTheDew(); // 1
}
};
在标有“1”的行上,我收到错误
class Command<void, void> has no member named doTheDew
我在这一点上已经尝试了很多,并且不明白我错过了什么。
答案 0 :(得分:1)
在标记为// 1
的行中立即失败,但在其他两个专业化版中实例化时也失败。
Command<int,void> c1; // fail
Command<void,int> c2; // fail
Command<int,int> c3; // OK
原因是没有专门化有doTheDew()
方法,因为每个专业化都是自己的类,有自己的成员。
您可以考虑将主模板和所有特化的可用方法移动到基类。不要忘记从那个基础派生主模板和专业化。
答案 1 :(得分:1)
正如0x499602D2指出的那样,模板只是模板生成类。所以每个模板专业化都是一个不同的类。您需要在所有专业化中提供doTheDew
声明/定义。
减少代码重复的一种方法是创建一个提供doTheDew
方法的基类,并使所有特殊化继承自它:
struct dothedew_impl
{
void doTheDew();
};
template<typename C>
class Command<C, void> : public dothedew_impl
{
public:
Command() {
this->doTheDew();
}
};
当然,如果doTheDew()
方法依赖于类的某个模板参数,那么您也可以将基类作为模板:
template<typename T>
struct dothedew_impl
{
void doTheDew();
};
template<typename C>
class Command<C, void> : public dothedew_impl<C>
{
public:
Command() {
this->doTheDew();
}
};
请注意,上一个this->
实施示例中的Command()
是必要的,因为template dependent names are resolved during second template parsing phase。 this->
用于强制编译器将doTheDev()
包含到类范围中,并将其移至第一阶段。