anon
anon

Reputation:

Invalid declarator before with map of struct?

I'm trying to map a mapping between strings and a custom struct, callable. However, it's giving me "invalid declarator". I've tried a bunch of things, like typedefing it (e.g. typdef struct _c { } callable;) but that just raises more errors.

I'm compiling with ideone.com, since I don't have a compiler at school but I still want to at least bang out decent code.

A minimum example (ideone link):

#include <vector>
#include <map>
#include <iostream>
#include <string>
using namespace std;

struct callable {
  virtual void operator()(vector<string> args) = 0;
}

std::map<std::string, callable> commands =
{
  { "cmd", struct : callable
    {
      operator()(vector<string> args) {
        out << "cmd called with args:" << endl;
        for (auto i = args.begin(); args.end() != i; ++i) out << *i << endl;
      }
    }
  }
}

int main() {
  vector<string> args = {"hello", "world"};
  commands["cd"](args);
}

And the error is:

prog.cpp:11:33: error: invalid declarator before 'commands'
 std::map<std::string, callable> commands =
                                 ^

The expected output:

cmd called with args:
hello
world

As a side note, please provide an answer to this question before answering the more general question of mapping strings to code, unless this approach can't work.

Upvotes: 2

Views: 6077

Answers (4)

SergeyA
SergeyA

Reputation: 62603

Syntax issues aside, your code smells Java. In C++ where functions are first-class citizens, you do not need to create callback classess for every possible callback. Instead, you simply pass function-like objects - either a pointer to function, or something wrapped inside std::function. The former is simpler, the latter is more powerful. I suggest to work with simple pointers first. For instance, your code might be looking like following:

void do_cmd(const std::vector<std::string>& args);
typedef void (*cmd_func)(const std::vector<std::string>& cmd_args);
std::map<std::string, cmd_func> cmd_map = { {"cmd", &do_cmd} };

int main() {
   (*cmd_map["cmd"])(args);
}

Upvotes: 3

faltarell
faltarell

Reputation: 334

I think you just lack a ';' after the closing brace of the struct declaration...

Upvotes: 1

MicroVirus
MicroVirus

Reputation: 5477

You forgot the extra semicolon after struct:

struct callable {
  virtual void operator()(vector<string> args) = 0;
}; // <--- ; is needed.

This is what gives you the compiler error.

Upvotes: 12

pcarter
pcarter

Reputation: 1628

callable is an abstract base class and can't be instantiated. Thus, you can't store an instance of one in a map. You can store a pointer to a ABC in a map, but don't use a raw pointer use a smart one, such as below:

std::map<std::string, std::unique_ptr<callable> > 

Upvotes: 2

Related Questions