- 类型擦除是一种编程技术,指程序在编写时并不显式依赖于其所使用的某些类型。当用于将抽象行为与特定实现分离时,是一种强大的设计工具。
- 其实现方式要么是通过多态对象和虚函数调用,要么是通过为擦除类型专门实现,并通过函数指针调用的函数。这会结合泛型编程,以自动构造此类多态对象或从模板生成函数,并确保具体化的类型始终与构造时提供的类型一致。
- 程序可以编写成,避免显式提及大多数类型的形式。类型由模板函数推导,并声明为 auto 或模板推导出的 typedef 类型。然而,auto 隐藏的对象的实际类型依赖于该对象所操作的所有类型(例如指针的删除器类型),擦除的类型完全不体现在对象类型中。如果能让编译器说明这个特定的 auto 具体代表什么,所有类型都会明确存在。但如果类型擦除了,即使是最详细的包含对象的声明也不会知道(例如 std::shared_ptr —— 这就是完整的类型,删除器类型并不在其中)。
- 类型通过为该类型生成的函数具体化:虽然其签名(参数)不依赖于擦除的类型,但函数体却依赖。通常,第一步是将其中一个参数从通用指针(如 void*)转换为指向擦除类型的指针。
- 与直接调用相同的可调用对象相比,类型擦除的性能总会带来一些开销:总是存在其他间接寻址及其关联的指针。几乎所有实现都使用运行时多态(虚函数或动态转换)或等效的函数指针虚拟表,这增加了时间(间接函数调用)和内存(虚拟指针)开销。最大的开销通常来自其他内存分配,这是为了存储编译时大小未知对象所必需。如果能够最小化此类分配并将其他内存限制在对象内部,运行时的总开销可能非常小(但内存开销仍然存在,并且此类优化通常会增加内存占用)。