Search code examples
c++polymorphismtype-erasuredynamic-dispatch

Visit a polymorphic type, like a variant without knowing the exact subtypes


There are times when knowing the actual subtype of a polymorphic object is beneficial - like ensuring no virtual calls happen in a loop where we invoke a virtual function repeatedly. Making std::variant extendable towards the end-users of a library is a huge pain, it's a lot nicer to have an interface instead.

Ideally, I could do something like this:

struct base {
    virtual void foo() = 0;
};

struct derived : base {
    virtual void foo() override {}
};

// Sample
base* b = new derived{};
b->invoke_with_subtype([](auto* subtype) {
    static_assert(std::is_same_v<decltype(subtype), derived*>);
});

Of course, life isn't that ideal, I'd need to inject that function somehow. I was thinking some kind of CRTP trick, but I keep running into the same problem again and again, that I just can't erase that passed generic lambda function.

TL;DR: Is it possible to do dynamic dispatch on polymorphic types without a lot of boilerplate and knowing all the subtypes in advance?


Solution

  • No.

    Solving the problem as described requires runtime/dynamic link time reification of template code. This is a feature that C++ lacks.

    Modest restrictions remove that need, but all have tradeoffs. Most require a list of supported types somewhere, or a list of supported operations.

    Fancy alternative object models permit splitting vtables from instances and "RLE"-ing types in buffers and similar, but that also doesn't do what you describe.

    TL;DR remains "No" is the answer to your question, you cannot do that.


    SO is best suited to concrete, practical problems. In my experience if you have an actual practical use case, 9/10 there is an implicit restriction in your practical use case that makes your problem solvable.

    Instead, you produce an abstract solition that would be sufficient to solve your real problem. The issue is that your abstract solution isn't possible to solve.

    Of course, 99/100 questions like this don't have an actual practical concrete problem they are solving.

    If you have an actual practical concrete problem, I encourage you to post a question about it instead of this abstraction. My hobby is finding SO posts whose sensible answer is "no" and providing insensible "yes" answers.