#include <cstddef>
#include <iostream>
class MenuItem {
public:
constexpr MenuItem (const char* label, size_t subitems)
: m_label (label), m_subitems (subitems) { }
virtual void onKey () const = 0;
virtual void onEvent () const = 0;
virtual void onDraw () const = 0;
const char* const m_label;
size_t m_subitems;
// int m_flags; // Keine Ahnung was das in deinem Code macht, hier würde man das Äquivalent hinpacken
// void *Data;
};
template <typename... Rest>
class MenuContainer {};
template <typename First, typename... Rest>
class MenuContainer<First, Rest...> {
public:
constexpr MenuContainer (const First& src, const Rest&... rest) : m_item (src), m_rest (rest...) {
static_assert (sizeof (First) == sizeof (MenuItem), "All menu items classes must have the same size!");
}
private:
const First m_item;
const MenuContainer<Rest...> m_rest;
};
template <>
class MenuContainer<> {};
template <typename... Items>
class Menu {
public:
constexpr Menu (const Items&... items) : m_items (items...) {}
const MenuItem& operator [] (size_t index) const { return ptr () [index]; }
size_t getSize () const { return sizeof...(Items); }
const MenuItem* begin () const { return ptr (); }
const MenuItem* end () const { return ptr ()+getSize (); }
private:
const MenuContainer<Items...> m_items;
const MenuItem* ptr () const { return reinterpret_cast<const MenuItem*>(&m_items); }
};
class MyMenuItem1 : public MenuItem {
public:
constexpr MyMenuItem1 (const char* label, size_t subitems)
: MenuItem (label, subitems) { }
virtual void onKey () const {
std::cout << "MyMenuAction1::onKey\n";
}
virtual void onEvent () const {
std::cout << "MyMenuAction1::onEvent\n";
}
virtual void onDraw () const {
std::cout << "MyMenuAction1::onDraw\n";
}
};
class MyMenuItem2 : public MenuItem {
public:
constexpr MyMenuItem2 (const char* label, size_t subitems)
: MenuItem (label, subitems) { }
virtual void onKey () const {
std::cout << "MyMenuAction2::onKey\n";
}
virtual void onEvent () const {
std::cout << "MyMenuAction2::onEvent\n";
}
virtual void onDraw () const {
std::cout << "MyMenuAction2::onDraw\n";
}
};
template <typename... Items>
constexpr const Menu<Items...> makeMenu (const Items&... items) {
return Menu<Items...> (items...);
}
constexpr const auto myMainMenu = makeMenu (MyMenuItem1 {"Hello", 0}, MyMenuItem2 {"World", 0});
int main () {
for (auto& item : myMainMenu) {
std::cout << item.m_label << std::endl;
}
myMainMenu [0].onDraw ();
myMainMenu [1].onKey ();
}