Elegant console based menus
What I've come up with so far are two classes, one that makes and shows a console based menu and one that handles the actual options and actions mapped to those options. But I can't figure out a simple and elegant way to allow functions with different parameters and return types. Here's what I have so far
Code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <list>
#include <map>
using namespace std;
// Create and display a console based menu
class ConsoleMenu {
public:
ConsoleMenu(string omsg): msg(omsg){};
void add(string opt) { options.push_back(opt); }
ostream& display();
private:
string msg;
list<string> options;
};
ostream& ConsoleMenu::display()
{
list<string>::const_iterator it = options.begin();
while (it != options.end())
cout<< *it++ <<'\n';
return cout<< msg <<flush;
}
// Map menu options to functions
class MenuOptions {
public:
void add(int opt, void (*fn)()) { actions[opt] = fn; }
bool getOpt();
void run() { actions[option](); }
private:
int option;
map<int, void (*)()> actions;
};
bool MenuOptions::getOpt()
{
if (cin>>option && actions.find(option) != actions.end())
return true;
if (!cin.good())
{
cin.clear();
int ch;
while ((ch = cin.get()) != '\n' && ch != EOF)
;
}
return false;
}
void a() { cout<<"\nOption 1\n"<<endl; }
void b() { cout<<"\nOption 2\n"<<endl; }
void c() { exit(0); }
int main()
{
ConsoleMenu menu("Choose an option: ");
MenuOptions mopt;
menu.add("1) Option 1");
menu.add("2) Option 2");
menu.add("3) Quit");
mopt.add(1, a);
mopt.add(2, b);
mopt.add(3, c);
while (1)
{
menu.display();
if (mopt.getOpt())
mopt.run();
else
cerr<<"\nInvalid option\n"<<endl;
}
}
What I can't figure out is how to have different types of functions for each call to run() without losing the really simple interface I have. Has anyone encountered a problem like this before? If so, what was your solution? :)