The first if
is always true
, since after the assignment, the test on the RHS of the comma operator will be true
.
Your simple program doesn't warrant the use of goto
. Also overkill would be my preference for handling such tasks, though: a function table.
I finished off an example. We start with a simple callback class. The callback interface comes with a default implementation that complains about the input.
struct Callback {
virtual ~Callback () {}
virtual void operator () (std::string k) const {
std::cout << "Unrecognized input: " << k << '\n';
}
};
This part defines the function table data structure, declares an API to initialize one, and the driver code that invokes the callback:
typedef std::map<std::string, const Callback *> CallbackMap;
static void init_table (CallbackMap &cbmap);
static void invoke_table (const CallbackMap &cbmap, std::string k)
{
CallbackMap::const_iterator i = cbmap.find(k);
if (i != cbmap.end()) (*i->second)(k);
else Callback()(k);
}
int main ()
{
CallbackMap cbmap;
std::string k;
init_table(cbmap);
std::cout << "What would you like to do?\nContinue or Exit\n";
std::cin >> k;
invoke_table(cbmap, k);
return 0;
}
The individual callback implementations are implemented as singletons with this helper macro:
#define CONST_SINGLETON(Name) \
public: \
static const Name & instance () { \
static const Name one; \
return one; \
} \
private: \
Name () {} \
Name (const Name &); \
void operator = (const Name &)
And each callback implementation does the simple action that was presented in your sample program:
class ExitCallback : public Callback {
void operator () (std::string) const { std::exit(0); }
CONST_SINGLETON(ExitCallback);
};
class ContinueCallback : public Callback {
void operator () (std::string) const {
std::cout << "You continued...\n";
}
CONST_SINGLETON(ContinueCallback);
};
The initialization routine populates the function table with the string that corresponds to the appropriate callback:
static void init_table (CallbackMap &cbmap)
{
static struct { const char *s; const Callback *cb; } init[] = {
{ "exit", &ExitCallback::instance() },
{ "Exit", &ExitCallback::instance() },
{ "continue", &ContinueCallback::instance() },
{ "Continue", &ContinueCallback::instance() },
{ 0, 0 }
};
for (int i = 0; init[i].s; ++i) {
cbmap[init[i].s] = init[i].cb;
}
};