Invoking a function over a sequence of CRTP derived instances

49 views Asked by At

Suppose I have a templated function that takes a generic parameter that sticks to the concept/interface of its CRTP base class like

template <typename Parser_T>
void print(Parser_T&& parser)

Now I want to iterate over a sequence of those CRTP derived instances to invoke this function. The best I came up was to use std::variant of all known sub classes, and use std::visit combined with a lambda to invoke the templated function.

Is there an easier way to do this, especially getting rid of the lambda? I don't have to store the instances homogeneous, some kind of a template trick list would be fine. But I have to able to specify the order, i.e. the instance sequence of course to invoke.

Example:

#include <iostream>
#include <array>
#include <variant>
#include <string>

template <class T>
struct parser_base
{
    std::string parse()
    {
        return static_cast<T*>(this)->parse_impl();
    }
};

struct parser_a : parser_base<parser_a>
{
    std::string parse_impl() {
        return "A\n";
    }

};

struct parser_b : parser_base<parser_b>
{
    std::string parse_impl() {
        return "B\n";
    }
};

template <typename Parser_T>
void print(Parser_T&& parser)  {
    std::cout << parser.parse();
}

int main() {
    using var_t = std::variant<parser_a, parser_b>;
    std::array<var_t,2> parser_list{parser_a{}, parser_b{}};

    for(auto &parser: parser_list) {
        std::visit([](auto &&arg) {
            print(arg);
        }, parser);
    }
}

0

There are 0 answers