获取派生模板实例化的运行时类型
Obtaining the runtime type of a derived template instantiation
我可以使用typeid
或dynamic_cast
在派生的基类实例之间切换。例如:
struct B { virtual ~B() {} };
struct D1 : B {};
struct D2 : B {};
void doit(B &b) {
if (dynamic_cast<D1 *>(&b)) foo1();
else if (dynamic_cast<D2 *>(&b)) foo2();
}
当派生类型是模板实例化时,我如何继续这样做?例如,我如何扩展上面的doit
函数来处理四种情况;也许使用下面的DT1
和DT2
类,用任意类型实例化?
template <typename T>
struct DT1 : B {};
template <typename T>
struct DT2 : B {};
与其在doit
函数中硬编码派生类的列表,不如维护某种foo
函数的注册表来调用每种类型。在最简单的形式中,这可能只是std::function<void(B&)>
的一个vector
,您只需循环并调用它们中的每一个。每个std::function
将负责检查类型是否匹配:
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&)>>
这样你就不必遍历整个注册表,但只要你没有大量的派生类,它可能就无关紧要。
然后,您只需在注册表中注册每种类型的派生类。可以创建一个帮助程序类,该类在其构造函数的注册表中注册函数:
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()
}
现场演示。
相关文章:
- 通过switch和static_cast访问多态对象的运行时类型
- 如何在void*指针下检查运行时类型(允许简单类型,没有基类)?
- 获取派生模板实例化的运行时类型
- 运行时类型推断和代码重复
- UWP,加载窗口运行时组件 == 请求的窗口运行时类型 "..." 未注册
- 为什么C++不按运行时类型销毁对象?
- 运行时类型定义
- 在C++中如何将运行时类型鉴别器映射到模板实例(无需手动枚举所有实例)
- 编译器不可知的运行时类型信息
- C++中高效的运行时类型检查
- 运行时类型信息的奇怪行为
- 运行时类型信息(为什么此代码不起作用)
- 运行时类型检查
- C++基于运行时类型实现强制转换
- C++运行时类型与 Python 模块不匹配
- 循环unique_ptrs的向量,并为运行时类型调用正确的重载
- 处理运行时类型未知的模板
- 自定义C++的运行时类型系统/库
- 基于运行时类型实例化构造函数
- 运行时类型在c++中的转换,如何