显式模板专用化和依赖名称查找问题



我正在尝试编写一个具有一些部分和显式专用化的类。不过,在名称查找怪癖方面遇到问题。现在我有:

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

在这一点上我已经尝试了很多,但不明白我错过了什么。

它在标记为 // 1 的行中立即失败,但在其他两个专业中实例化时也会失败。

Command<int,void> c1; // fail
Command<void,int> c2; // fail
Command<int,int> c3; // OK

现场示例

原因是没有一个专用化具有doTheDew()方法,因为每个专用化都是其自己的类,具有自己的成员。

您可以考虑将应该可用于主模板和所有专用化的方法移动到基类中。 然后不要忘记从该基础派生主模板和专用化。

正如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();
    }
};

请注意,最后一个Command()实现示例中的this->是必需的,因为在第二个模板分析阶段解析模板相关名称。this->用于强制编译器将doTheDev()包含在类作用域中,并将其移动到第一阶段。

最新更新