Runtime polymorphism without dynamic memory allocation

Another one on polymorphism

This time is about not using heap allocation while having runtime polymorphism. I will use std::variant for this, so nothing new. What got my attention is how the polymorphic objects are used if stored in a variant. This is the main topic of this short article.

The use case is a factory function that creates polymorphic objects.

Virtual inheritance

I’m taking it step by step, starting with the classic approach using virtual inheritance. For this, I need some pointers, of course.

#include <cassert>
#include <memory>

struct P {
    virtual int f(int) const = 0;
    virtual ~P() = default;
};

struct A : P {
    int f(int in) const override {return in + 1;}
};

struct B : P {
    int f(int in) const override {return in + 2;}
};

std::unique_ptr<P> factory(char o) {
    switch(o) {
        case 'a': return std::make_unique<A>();
        default: return std::make_unique<B>();
    }
}

int main() {
    assert(factory('a')->f(1) == 2);
    assert(factory('b')->f(1) == 3);
}

std::variant

The std::variant solution is to have a variant with all the possible types instead of pointers to the types. This will avoid heap allocations. And it will break the need for inheritance, having objects that are not coupled to a base class anymore. Continue reading Runtime polymorphism without dynamic memory allocation