Type erasure and polymorphic interface objects

Runtime polymorphism in C++

The canonical way of doing runtime polymorphism in C++ has always been virtual functions and inheritance. Compared to alternative solutions found in other languages, such as:

  • Interface in Go
  • Trait object in Rust

, the virtual function plus inheritance approach is often considered inferior, for the following reasons:

  • Intrusive design: All implementers of an interface must inherit from it. The implementation object also has to make room for the vtable!
  • Mandates reference semantics: You can only use the interface polymorphically through pointers or references. A factory function has to return std::unique_ptr<InterfaceType>, which is messy. (To be fair, interface objects also require dynamic allocation internally)
  • Performance cost: They are often found to be slower than alternatives.

polymorphic object

A polymorphic object type defines a set of methods. Such object can then store another object of abitary type, that implements the defined set of methods.

People have been writing such implementations for years, such as Poly, dyno, proxy.

benefits

  • Allows value-semantics, and copying. Although polymorphic objects still require dynamic allocation in the general case, the user does not need to care about it. Copying is possible, by storing function pointers of copying operations. Virtual inheritance on the other hand, does not play nicely with copy constructors!
  • Allows Small buffer optimization. Since they’re custom objects, SBO is possible, compared to std::unique_ptr<InterfaceType>.
  • Allows duck typing. Although this isn’t always desired.

Type erasure

Actually, we already have a limited version of polymorphic object in C++: std::function. It only knows about the operator(), but the idea is similar: Use type-erasure.

For polymorphic objects, we need to keep the function pointers somewhere, but for potentially multiple member methods.

To be continued…

Licensed under CC BY-NC-SA 4.0
Last updated on Dec 26, 2023 00:00 UTC
comments powered by Disqus