模板的通用矢量

时间:2015-01-25 11:40:56

标签: c++ templates

对我来说,模板的通用向量是可以使用任何参数列表的模板的向量。喜欢这个

vector<Foo<?>> foos;
foos.push_back(Foo<int>(5));
foos.push_back(Foo<Bar>(Bar()));
foos.push_back(Foo<string>("bar"));

编辑:

这就是我需要这个

的原因
#ifndef EVENT_DISPATCHER_H
#define EVENT_DISPATCHER_H
// #include <boost/signals2.hpp>
#include <string>
#include <vector>
#include <functional>
#include <map>

namespace Whitedrop {
    template <typename... T> class EventDispatcher {
    public:

        EventDispatcher(std::string eventID)
        {

        }

        void on(std::function<void(T...)> callback)
        {
            mCallbacks.push_back(callback);
        }

        void trigger(T&... args)
        {
            for (auto f : mCallbacks)
                f(args...);
        }

    protected:
        std::vector<std::function<void(T...)>> mCallbacks;

    };
    std::map<std::string, EventDispatcher<?> > dispatchers; // HERE <--------

    template<typename... T> void registerListener(std::string eventID, std::function<void(T...)> callback)
    {
        if (!dispatchers.count(eventID))
        {

            dispatchers[eventID] = new EventDispatcher<T...>(eventID);

            return;
        }
        dispatchers.find(eventID)->second.on(callback);
        //std::shared_ptr<Chunk> chunk = mChunks.find(pos)->second;

    }

    template<typename... T> void invokeListener(std::string eventID, T... args)
    {
        if (!dispatchers.count(eventID))
        {

            return;
        }
        dispatchers.find(eventID)->second->trigger(args...);
    }
};
#endif

似乎不太可能,我该如何解决我的问题?

3 个答案:

答案 0 :(得分:3)

不,那是不可能的。类模板是模板,而不是类型。 std::vector模板需要类型作为其第一个参数,而不是模板。

您可以使用类模板生成类型,但必须为std::vector模板的每个实例选择一种特定类型。


更一般地说,模板参数的性质告诉您可以使用哪种参数。在C ++中有三个“本体层”:值(“具有类型的东西”),类型(“ 类型的东西”)和模板(“三个“)。每个都可以显示为模板参数:

template < int A                        // Value (int prvalue)
         , typename B,                  // Type
         , template <typename> class C  // Template
         > struct Foo {};

Foo<10, double, std::allocator> foo;
//   A     B            C

答案 1 :(得分:2)

简单的答案是否定的。

编译器需要弄清楚类型和大小。

修改

使用继承

例如

class Event {
   private:
      std::string m_id;
   public:
       Event(std:string &id) : m_id(id) { }
       std:string EveentId() const { return m_id;}
       virtual void DoEvent() = 0;
};

class MyEvent : Event {
   public:
      MyEvent() : Event("MyEvent") { }
       DoEvent() { std::cout << "MyEvent" << std::endl;
};

然后有一个事件列表

std::vector<std::shard_ptr<Event>> events;

events.push_back<std::make_shared<MyEvent>());

events[0]->DoEvent();

答案 2 :(得分:1)

std :: vector是一个同类容器,这意味着它只能包含一种类型。注意Foo&lt;&gt;是一个类型不是单一类型的系列,std :: vector的类型因模板参数而异。

现在,您可以使用我能想到的两种方法来实现您想要的效果,第一种是通过擦除类型,例如您可以使用std::vector<boost::any>,但请注意它会完全删除类型(类型信息)丢失了,并且不是编译时操作。

第二种方法是使用tuple,这是一个编译时固定大小的容器,这意味着你不能在运行时添加新元素,因为每个对象都在编译时确定。