模板的通用向量
Generic vector of 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
既然这似乎不可能,我该如何解决我的问题?
简单的回答是否定的。
编译器需要计算类型和大小。
编辑
使用继承
例如
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();
不,那不可能。 Class 模板是模板,不是类型。 std::vector
模板需要 type 作为第一个参数,而不是模板。
您可以使用 class 模板来生成类型,但您必须为 std::vector
模板的每个实例化选择一个特定类型。
更一般地说,模板参数的性质告诉您可以使用哪种参数。在 C++ 中有三种 "ontological tiers":值("things that have types), types (" 属于 类型的东西)和模板("things that make any of the three")。每个都可以作为模板参数出现:
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
std::vector是同构容器,也就是说只能包含一种类型。请注意,Foo<> 是一系列类型,而不是单一类型,std::vector 的类型因模板参数而异。
现在,你可以使用我能想到的两种方法来实现你想要的,第一种是擦除类型,例如你可以使用std::vector<boost::any>
,但请注意它完全擦除类型(类型信息丢失),并且不是编译时操作。
第二种方法是使用tuple,这是一个编译时固定大小的容器,这意味着你不能在运行时添加新元素,因为每个对象的类型在编译时确定。
对我来说,模板的通用向量是可以采用带有任何参数列表的模板的向量。像这样
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
既然这似乎不可能,我该如何解决我的问题?
简单的回答是否定的。
编译器需要计算类型和大小。
编辑
使用继承
例如
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();
不,那不可能。 Class 模板是模板,不是类型。 std::vector
模板需要 type 作为第一个参数,而不是模板。
您可以使用 class 模板来生成类型,但您必须为 std::vector
模板的每个实例化选择一个特定类型。
更一般地说,模板参数的性质告诉您可以使用哪种参数。在 C++ 中有三种 "ontological tiers":值("things that have types), types (" 属于 类型的东西)和模板("things that make any of the three")。每个都可以作为模板参数出现:
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
std::vector是同构容器,也就是说只能包含一种类型。请注意,Foo<> 是一系列类型,而不是单一类型,std::vector 的类型因模板参数而异。
现在,你可以使用我能想到的两种方法来实现你想要的,第一种是擦除类型,例如你可以使用std::vector<boost::any>
,但请注意它完全擦除类型(类型信息丢失),并且不是编译时操作。
第二种方法是使用tuple,这是一个编译时固定大小的容器,这意味着你不能在运行时添加新元素,因为每个对象的类型在编译时确定。