Dynamic Polymorphism vs. std::variant: Debunking Myths About std::visit Speed

Exploring the misconceptions surrounding dynamic polymorphism and std::variant in C++.

5 min readProgramming

In the realm of modern C++, a prevalent belief has emerged: traditional dynamic polymorphism via virtual functions is seen as outdated and inefficient, particularly regarding CPU cache friendliness. Advocates often propose using std::variant alongside std::visit as a superior alternative. Many articles circulate online claiming that std::visit achieves dispatching in constant time O(1), effectively rendering classical object-oriented programming obsolete. However, these comparisons frequently fall into methodological pitfalls, contrasting a vector of pointers (std::vector<Base*>) with a vector of raw objects (std::vector<std::variant>). While std::variant may appear to excel, this advantage stems not from the mechanics of function calls but rather from its data locality within the CPU cache. To clarify this, we must level the playing field and isolate the call mechanics. Consider a realistic scenario where objects are heavy, created dynamically over time, and scattered across the heap, while we operate on arrays of their addresses. We will directly compare std::vector<Base*> with std::vector<std::variant<TypeA, TypeB, TypeC>*> under separate compilation conditions, where the optimizer cannot apply total inlining.

Programming