明确的模板专业化&依赖名称查找问题

时间:2014-01-13 21:27:02

标签: c++ templates

我正在尝试编写一个具有部分和显式特化的类。虽然名字查找怪癖有问题。现在我有:

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

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

2 个答案:

答案 0 :(得分:1)

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

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

Live example

原因是没有专门化有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 phasethis->用于强制编译器将doTheDev()包含到类范围中,并将其移至第一阶段。