I am coding a trivial template struct (in C++) that can display a formated "menu" in the console. I'm doing this mostly to play around with variadic arguments. The struct's template works by automatically deducing an input type (InputTy
), a prompt type (PromptTy
, probably usually either a std::string
or const char*
), and a parameter pack for the message (class... MsgTypes
). The class's declaration looks like:
template<class InputTy, class PrompTy, class... MsgTypes>
struct Menu
{
// ... Stuff in here ... //
};
What I'd like to do with this class is save the MsgTypes
as a sort of "variadic class attribute". Essentially, this would look like:
template<class InputTy, class PromptTy, class... MsgTypes>
struct Menu
{
public:
Menu(PromptTy prompt_text, MsgTypes... menu_text) : prompt_text(prompt_text),
menu_text(menu_text) {}
// Displays the formatted menu (uses variadic attribute)
inline void display()
{
display_recurse(menu_text);
std::cout << std::endl << prompt_text;
std::cin >> input_var; std::cin.ignore(10000, '\n');
/* ... Etc ... */
}
protected:
InputTy input_var;
PromptTy prompt_text;
MsgTypes... menu_text; // Variadic attribute
// Recursive function for displaying the text of a menu
template<typename Ty, typename... Types>
inline void display_recurse(Ty cur_line, Types next_lines)
{
std::cout << cur_line << std::endl;
display_recurse(next_lines);
}
// No-arg function overload for recursive generic function with parameter pack
inline void display_recurse() {}
};
Is it possible ... to use parameter packs as class attributes in C++?
Not quite. Argument packs can only be expanded into argument lists, expressions or initialisers, but not into declarations.
There is a standard template std::tuple
, which achieves essentially what you might be trying to do. It is a template class with each variadic type argument as a member object. So, in your case you might have a member:
std::tuple<MsgTypes...> menu_text;
In case you're wondering, how does tuple itself achieve this: You can take one template argument as non-pack, have that as member and inherit another instance of the template recursively with the rest of the parameter pack.