【问题标题】:Storing multiple types of a templated class into a container将多种类型的模板化类存储到容器中
【发布时间】:2011-11-10 14:40:51
【问题描述】:

如果我有一个带有模板的类:

template<typename T>
class foo{
    T m_a;

    foo(T a){
        m_a = a;
    };

    ~foo(){

    };
};

有没有办法存储它的多个变体?

例如一个可以同时存储指向foo&lt; int &gt;foo&lt; string &gt;的指针的向量?

编辑更多信息

我想隐藏这个的实现:

EventListener<string> ev1;
EventListener<int, int> ev2;
EventListener<int, string, double> ev3;

ev1(&Events::nameChange, &nameChangeCallback);
ev2(&Events::healthChange, &healthChangeCallback);
ev3(&Events::newUser, &newUserCallback);

ev1.processEvents();
ev2.processEvents();
ev3.processEvents();

进入这个:

EventManager em;
em.listen(&Events::nameChange, &nameChangeCallback);
em.listen(&Events::healthChange, &healthChangeCallback);
em.listen(&Events::newUser, &newUserCallback);
em.processEvents();

EventManager 需要创建 EventListener 并将其存储到一个向量中,以便能够记住它们并在析构函数中删除它们。

这就是我卡住的地方。

【问题讨论】:

  • 您可以为您的用户定义类型存储指向基类的指针。

标签: c++ templates containers


【解决方案1】:

如果你想要,例如std::vector&lt;foo&lt;T&gt;*&gt;,那么你需要使用非模板化的基类。它需要使用动态调度,所以所有的公共接口都应该声明为virtual

struct foo_base {
    virtual ~foo_base() {}
    virtual void something() = 0;
};

template <typename T>
struct foo : foo_base {
    // ...
    void something() { /* do something with T */ }
};

那么你的容器是std::vector&lt;foo_base*&gt;。另一种可能更好的方法是使用boost::variant。这限制了您可以存储的类型数量,但同时不需要基类和虚拟接口。

typedef boost::variant<foo<int>, foo<std::string>> foo_variants;
std::vector<foo_variants> v;

第三种方法是使用boost::any,但无论您在哪里使用它们都需要boost::any_cast,并且绝对允许将任何内容存储在向量中。

std::vector<boost::any> v;

【讨论】:

  • 如果something() 需要使用T 作为参数,例如something(T a)。这还能用吗?
  • @Blizter:不,除非你把它打包到例如boost::any 并将其解压缩到具体的子类中。所有类中的接口必须相同才能使基类方法起作用。
  • 为什么必须将整个公共接口声明为虚拟的?我不能有一个非虚拟公共成员并从子模板类中使用它吗?
【解决方案2】:

类模板的不同实例化是不同的(从编译器的角度来看完全不相关)类型,所以this question 适用。

【讨论】:

  • 这带来了另一个问题,如果类模板具有相同的功能,并且它们被存储。我可以在不知道它们的类类型的情况下调用这些函数吗?
  • 现在你在谈论多态性。您可以通过使您的类模板继承自定义要以多态方式调用的函数的类来做到这一点。然后你必须在你的容器中存储指针,你就可以开始了。在我输入此评论时,@Cat Plus Plus 发布了一个答案来解释这一点。
猜你喜欢
  • 2018-08-16
  • 2019-08-20
  • 1970-01-01
  • 2013-07-11
  • 2017-09-20
  • 2017-05-30
  • 2018-05-09
  • 1970-01-01
相关资源
最近更新 更多