可变参数模板类未完全扩展

38489344

我正在尝试创建类似于类型安全多队列的东西。这个想法是,当我推送一个项目时,它将被添加到一个由相同类型的对象组成的队列中。

所有队列都将具有一个公共接口(queue_intf在这种情况下),该接口将进行一些处理。

我出现的代码如下:

#include <queue>
#include <vector>
#include <memory>
#include <stdlib.h>

class queue_intf {
public:
    virtual void process(void) = 0;
};

template <typename T>
class queue : public queue_intf {
public:
    std::queue<T> q_;
    static const char* name()
    {
        return typeid(T).name();
    }
    virtual void process(void) override {
        printf("process: %s\n", this->name());
    }
    void push(T &a) {
        printf("push: %s\n", this->name());
    }
};

template <typename...>
class queues {
public:
    std::vector<queue_intf *> qs_;
    void process(void) {
        for (auto q: this->qs_) {
            q->process();
        }
    }
};

template <typename T, typename... Ts>
class queues<T, Ts...> : public queues<Ts...> {
public:
    queue<T> q_;
    queues() {
        this->qs_.push_back(&this->q_);
    }
    void push(T &v) {
        q_.push(v);
    }
};

class a {
};

class b {
};

int
main (int argc, char *argv[])
{
    queues<a, b> qs;
    a ai;
    b bi;

    qs.push(ai);
    qs.process();
    qs.push(bi);
}

但是,当我编译它时,出现以下错误:

main.cc: In function ‘int main(int, char**)’:
main.cc:65:15: error: no matching function for call to ‘queues<a, b>::push(b&)’
     qs.push(bi);
               ^
main.cc:45:10: note: candidate: void queues<T, Ts ...>::push(T&) [with T = a; Ts = {b}]
     void push(T &v) {
          ^~~~
main.cc:45:10: note:   no known conversion for argument 1 from ‘b’ to ‘a&’

我期望queue类具有void push(b &v)方法,但似乎没有。

知道为什么吗?

编辑:

这是一个较小的示例(否std:vector):

template <typename...>
class queues {
};

template <typename T, typename... Ts>
class queues<T, Ts...> : public queues<Ts...> {
public:
    void push(T &v) {
    }
};

class a {
};

class b {
};

int
main (int argc, char *argv[])
{
    queues<a, b> qs;
    a ai;
    b bi;

    qs.push(ai);
    qs.push(bi);
}
山姆·瓦尔沙夫奇克

为了说明这一点,让我们使用一个简化的示例,您只有两个类:

class base {

public:
    void method(int *);
};

class derived : public base {

public:

    void method(char *);
};

您尝试调用它:

derived d;

int i;

d.method(&i);

这失败了。名称查找从给定的derived开始,并找到具有指定名称的匹配类方法:method但是,其参数不匹配,因此格式不正确。如果derived该类同时具有这两种方法,则重载解析将选择匹配的一个。但是一旦找到具有指定名称的类方法,就不会在任何父类中搜索具有相同名称的任何其他方法。仅当派生类没有具有指定名称的任何方法时,名称查找才会继续使用父类。

推杆

using base::method;

在派生类中,将基类导入method到派生的名称空间中,此时一切都与常规重载解析一样工作。

这就是为什么您需要using使用递归模板进行声明的原因第二个派生模板从第一个派生模板导入它,第二个派生模板从第二个派生模板导入所有内容,依此类推。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章