而是在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