This code snippet implements two classes - A command handler that takes in a command name and a list of supported sub-commands and a Meta class that holds all such supported "Commands".
I'm looking for a way to initialized these top level CommandHandler
objects (cmd_one_
, cmd_two_
) together, instead of initializing the individual objects, say like this:
MetaCommandWrapper<COMMAND_ONE,
<cmd_one::SUBCMD_ONE,
cmd_one::SUBCMD_TWO
>,
COMMAND_TWO,
<cmd_two::SUBCMD_ONE,
cmd_two::SUBCMD_TWO
>
> meta_commands_;
That would make it easier to loop through supported commands in MetaCommands
and call the appropriate CommandHandler
class's method. For example, a method execute
issued like this: m.execute(COMMAND_ONE, cmd_one::SUBCMD_TWO)
would execute command one's second subcommand, and so on.
How do I go about doing that?
#include <cstdint>
enum meta_commands
{
COMMAND_ONE,
COMMAND_TWO
};
namespace cmd_one
{
enum subcmd
{
SUBCMD_ONE,
SUBCMD_TWO
};
}
namespace cmd_two
{
enum subcmd
{
SUBCMD_ONE,
SUBCMD_TWO
};
}
template <uint32_t Command, uint32_t...SubCommands>
class CommandHandler
{
};
class MetaCommands
{
private:
CommandHandler<meta_commands::COMMAND_ONE, cmd_one::SUBCMD_ONE, cmd_one::SUBCMD_TWO> cmd_one_;
CommandHandler<meta_commands::COMMAND_TWO, cmd_two::SUBCMD_ONE, cmd_two::SUBCMD_TWO> cmd_two_;
};
int main()
{
MetaCommands m;
return 0;
}
I'm not sure exactly what you need but it seems like MetaCommands
should be a class template since you want to create it with different template parameters:
template <class... CmdHandlers>
class MetaCommands {};
This would then not let you create an instance exactly as you asked for, but it'll be pretty similar:
int main() {
MetaCommands<
CommandHandler<COMMAND_ONE, cmd_one::SUBCMD_ONE, cmd_one::SUBCMD_TWO>,
CommandHandler<COMMAND_TWO, cmd_two::SUBCMD_ONE, cmd_two::SUBCMD_TWO>
> meta_commands_;
}
You could then extract or fold over the template arguments as you wish. Say you add a function for printing the Command
and SubCommand
s of a CommandHandler
template <uint32_t Command, uint32_t... SubCommands>
class CommandHandler {
friend std::ostream& operator<<(std::ostream& os, const CommandHandler&) {
os << "Cmd: " << Command << " Subs:";
(..., (os << ' ' << SubCommands));
return os;
}
};
and add the same to MetaCommands
:
template <class... CmdHandlers>
class MetaCommands {
private:
friend std::ostream& operator<<(std::ostream& os, const MetaCommands&) {
(..., (os << CmdHandlers{} << '\n'));
return os;
}
};
You'd be able to print it in main
like so:
int main() {
MetaCommands<
CommandHandler<COMMAND_ONE, cmd_one::SUBCMD_ONE, cmd_one::SUBCMD_TWO>,
CommandHandler<COMMAND_TWO, cmd_two::SUBCMD_ONE, cmd_two::SUBCMD_TWO>
> meta_commands_;
std::cout << meta_commands_ << '\n';
}
Output:
Cmd: 0 Subs: 0 1
Cmd: 1 Subs: 0 1