Polymorphic Dispatch: Virtual Function vs CRTP
Question 50 / 51 • Correct so far: 0 (0 answered)
Virtual Call
struct Transformer {
virtual double transform(double x) const = 0;
virtual ~Transformer() = default;
};
struct ScaleTransformer : Transformer {
double transform(double x) const override { return x * kBase; }
};
double applyAll(Transformer* t, int n) {
double val = 1.0;
for (int i = 0; i < n; ++i)
val = t->transform(val);
return val;
}
double result = applyAll(&t, kCallCount); Crtp Call
template <typename Derived>
struct Transformer {
double transform(double x) const {
return static_cast<const Derived*>(this)->transformImpl(x);
}
};
struct ScaleTransformer : Transformer<ScaleTransformer> {
double transformImpl(double x) const { return x * kBase; }
};
template <typename T>
double applyAll(const Transformer<T>& t, int n) {
double val = 1.0;
for (int i = 0; i < n; ++i)
val = t.transform(val);
return val;
}
double result = applyAll(t, kCallCount); Shared test data (shared-setup)
constexpr int kCallCount = 100000;
constexpr double kBase = 1.000001; Which snippet is faster?
Snippet B is faster. A virtual call requires an indirect jump through the vtable — the CPU loads the vtable pointer, then the function pointer, then jumps to it — and the call site resists inlining. CRTP resolves the call at compile time, so the compiler can inline the body and optimise across loop iterations.
Benchmark results
| Snippet | CPU time / iteration | Speedup |
|---|---|---|
| Crtp Call | 57 us | 1.6× |
| Virtual Call | 92.8 us | 1.0× |
Explore the source
Open in Compiler ExplorerQuiz complete. You can return to the question list to restart and compare.