而是在doit
功能硬编码派生类的列表,你可以保持某种foo
功能注册表的呼吁每种类型。最简单的形式可能是vector
的std::function<void(B&)>
,你只需循环并调用它们中的每一个。
auto& doitRegistry(){
static std::vector<std::function<void(B&)>> registry;
return registry;
}
void doit(B &b) {
for (auto& f : doitRegistry()) {
f(b);
}
}
如果你想成为更聪明的注册表可能会像std::unordered_map<std::type_index, std::function<void(B&)>>
,这样你就不必遍历整个注册表,但只要:如果类型匹配每个std::function
将负责检查你没有大量的派生类,它可能并不重要。
然后你只需要在注册表中注册每种类型的派生类。您可以创建在其构造函数登记处登记功能的辅助类:
struct DoItRegistration {
DoItRegistration(std::function<void(B&)> foo) {
doitRegistry().push_back(std::move(foo));
}
};
,打造每派生类这个类的静态实例:在第一次使用的那么
template <typename T>
struct DT1 : B {
DT1() {
registerWithDoIt();
}
static DoItRegistration& registerWithDoIt() {
static DoItRegistration registration([](B &b){
if (dynamic_cast<DT1<T>*>(&b)){
foo1();
}
});
return registration;
}
};
那派生类它本身注册doit
注册表并在需要时将被称作:
int main() {
DT1<double> d1;
DT1<int> d2;
DT2<double> d3;
DT1<double> dupeType;
doit(d3); // calls foo2()
}
Live demo。
*“我该如何继续下去”* - 通过使'doit'成为函数模板。你真正要求的是范式的混合体(编译模板类型与运行时动态类型)。这不会很好。 – IInspectable
这可能会有助于描述你的总体目标,因为有人可能有不同的方式来处理这个问题,这会更好地工作。另外,您可以考虑查看[Boost.Variant](http://www.boost.org/doc/libs/1_64_0/doc/html/variant.html)。 – SirGuy