Search code examples
c++templatesc++17variadic-templatesfunction-templates

How to remove this kind of duplication (for cycle over types)?


I have code like this:

template<class Command>
void registerCmd() {
    Command x{};
    // do something with x...
}

namespace Cmd
{
    struct GET { /* some methods */ };
    struct GETSET { /* some methods */ };
    struct DEL { /* some methods */ };

    void registerCommands() {
        registerCmd<GET>();
        registerCmd<GETSET>();
        registerCmd<DEL>();
    }
}

I like how the code turns out. I was wondering if there is a way this code to be changed to something like this:

namespace Cmd 
{
    void register() {
        // this does not compile
        for (TYPE in{ GET, GETSET, DEL })
            registerCmd<TYPE>();
    }
}

May be with variadic templates?


Solution

  • You can not have a collection of different types in a range based for loop, unless you have them in an array of std::variant, std::anyor such types.

    If you're willing to make the registerCommands template function which has variadic template arguments as template parameter, with the help of fold expression (since ) you might do (provided that the number types are known at compile time):

    template<typename... Types>
    void registerCommands() {
        (registerCmd<Types>(), ...);
    }
    

    and function calling

    Cmd::registerCommands<Cmd::DEL, Cmd::GETSET, Cmd::GETSET>();
    

    Live Demo