类型擦除(Type Erasure)顾名思义就是把类型信息擦除,这种代码可以处理来自多个类或模板的对象,而不需要知道即将对其操作的对象的类型是什么。类型擦除主要用于泛型编程,可以编写出能接受任意类型参数的函数和类,只要它们提供了你需要的操作,这意味着只需要关心它的行为即可,而不用在意其具体实现。


  • void:适用于C风格的API设计和处理一些低级操作,如直接内存操作等等。但在现代C++编程中尽量避免使用void,因为它并不安全,不能提供类型检查。
  • 虚函数:虚函数主要用于实现“运行时多态”,即在运行时选择调用哪个类的哪个函数。适用于需要在运行时改变行为,或者处理由多种不同类型对象组成的集合的场景。并且虚函数的实现十分的简单易懂(效率也不见得差特别多)。
  • std::variant:适合在有限的、确定的类型集合中进行类型擦除。比如作为函数返回值,需要返回不同类型值的场景,或者需要存储有限种类型的容器等。
  • CRTP:适用于在编译时需要确定类型,且需要提供高性能的场景。比如当你需要为多个类型提供相同的接口,但又不想付出虚函数的开销时可以使用,但是需要注意是否类层次结构是否比较复杂,那么使用CRTP会比较繁琐。
  • Concept-based Polymorphism:适用于需要提供强类型检查,且接口适用于多个类型的场景。Concepts提供了更好理解的代码表达形式和编译时的错误检查和信息,适合实现泛型编程和模板库。

这就是C++实现一个特性的过程中有着茫茫多的实现方案,在类型擦除的实现这个足足提供了五种方案,给选择困难症来了很大的痛苦,虽然条条大路通罗马,但是你不能保证你绕了多少路啊。得清楚每种方案的优劣才可以最终下判断,这就是C++的折磨之处。五种方案中第一个void*不提倡使用,但是后面四种都是有在使用的,并且除了虚函数其他三种都可以在编译期完成,性能上是更优的。

WRITE-BUG研发团队衷心希望【WRITE-BUG数字空间】可以给每位同学一个属于自己的秘密空间,同时祝愿大家在“公开圈子”世界里,遇见志同道合的伙伴们,因为我们与大家一样,都曾孤独前行着。

理解 C++ 类型擦除_泛型编程

理解 C++ 类型擦除_类型擦除_02

理解 C++ 类型擦除_泛型编程_03