Hos*_*ork 5 c++ design-patterns rtti c++11
假设我有一系列类都可以实现相同的接口,可能用于调度:
class Foo : public IScheduler {
public:
Foo (Descriptor d) : IScheduler (d) {}
/* methods */
};
class Bar : public IScheduler {
public:
Bar (Descriptor d) : IScheduler (d) {}
/* methods */
};
Run Code Online (Sandbox Code Playgroud)
现在假设我有一个Scheduler类,你可以要求为给定的描述符启动一个IScheduler派生类.如果它已经存在,您将获得它的引用.如果一个不存在,那么它会创建一个新的.
一个假设的调用将是这样的:
Foo & foo = scheduler->findOrCreate<Foo>(descriptor);
Run Code Online (Sandbox Code Playgroud)
实现它需要一个映射,其键(描述符,RTTI)映射到基类指针.然后你必须dynamic_cast
.我猜这些东西都是这样的:
template<class ItemType>
ItemType & Scheduler::findOrCreate(Descriptor d)
{
auto it = _map.find(SchedulerKey (d, typeid(ItemType)));
if (it == _map.end()) {
ItemType * newItem = new ItemType (d);
_map[SchedulerKey (d, typeid(ItemType))] = newItem;
return *newItem;
}
ItemType * existingItem = dynamic_cast<ItemType>(it->second);
assert(existingItem != nullptr);
return *existingItem;
}
Run Code Online (Sandbox Code Playgroud)
想知道是否有人有办法实现类似的结果而不依赖于这样的RTTI.也许每种计划的项目类型都有自己的地图实例的方式?设计模式,还是......?
函数或类静态成员的地址保证是唯一的(据我们所知<
),因此您可以使用这样的地址作为键.
template <typename T>
struct Id { static void Addressed(); };
template <typename ItemType>
ItemType const& Scheduler::Get(Descriptor d) {
using Identifier = std::pair<Descriptor, void(*)()>;
Identifier const key = std::make_pair(d, &Id<ItemType>::Addressed);
IScheduler*& s = _map[key];
if (s == nullptr) { s = new ItemType{d}; }
return static_cast<ItemType&>(*s);
}
Run Code Online (Sandbox Code Playgroud)
注意使用operator[]
避免双重查找并简化功能体.