The big problem with virtual calls is it hinders inlining, but if you design your API correctly that can usually be optimised away by design (put loops inside the call, don't call inside a loop)
In such cases I prefer using std::variant instead of inheritance, but this works only if all possible types are known ahead of time.
A vector of variants still wouldn't be optimal. Better to use something like
https://www.boost.org/doc/libs/latest/doc/html/poly_collecti...
Transpose.