Smash
Smash

Reputation: 3802

c++ std::map of heterogeneous function pointers

Is it possible to store pointers to various heterogenous functions like:

In the header:

int  functionA (int param1);
void functionB (void);

Basically this would the part I don't know how to write:


typedef ??boost::function<void(void)>?? functionPointer;

And afterwards:

map<char*,functionPointer> _myMap;

In the .cpp

void CreateFunctionMap()
{
    _myMap["functionA"] = &functionA;
    _myMap["functionB"] = &functionB;
    ...
}

And then reuse it like:

void execute(int argc, char* argv[])
{

    if(argc>1){
        int param = atoi(argv[1]);
        int answer;
        functionPointer mfp;
        mfp = map[argv[0]];
        answer = *mfp(param);
    }
    else{
        *map[argv[0]];
    }
}

etc.

Thanks

--EDIT--

Just to give more info:

The reason for this question is that I am implementing a drop-down "quake-style" console for an already existing application. This way I can provide runtime command line user input to access various already coded functions of various types i.e.:

 /exec <functionName> <param1> <param2> ...

Upvotes: 2

Views: 1698

Answers (5)

Alexandre C.
Alexandre C.

Reputation: 56956

You can use

boost::variant<
    boost::function<void(void)>,
    boost::function<void(int)> >

Upvotes: 3

Tim
Tim

Reputation: 9172

If you want to have "pointer to something, but I'm not going to define what, and it could be a variety of things anyway" you can use void *.

But you really shouldn't.

void * is purely a pointer. In order to do anything with it, you have to cast it to a more meaningful pointer, but at that point, you've lost all type safety. What's to stop someone from using the wrong function signature? Or using a pointer to a struct?

EDIT

To give you a more useful answer, there's no need to put this all into a single map. It's ok to use multiple maps. I.e.

typedef boost::function<void(void)> voidFunctionPointer;
typedef boost::function<int(int)>   intFunctionPointer;

map<std::string, voidFunctionPointer> _myVoidMap;
map<std::string, intFunctionPointer > _myIntMap;

void CreateFunctionMap()
{
  _myVoidMap["functionA"] = &functionA;
  _myIntMap["functionB"] = &functionB;
  ...
}

void execute(int argc, char* argv[])
{

  if(argc>1){
    int param = atoi(argv[1]);
    int answer;
    // todo: check that argv[0] is actually in the map
    intFunctionPointer mfp = _myIntMap[argv[0]];
    answer = mfp(param);
  }
  else{
    // todo: check that argv[0] is actually in the map
    voidFunctionPointer mfp = _myVoidMap[argv[0]];
    mfp();
  }
}

Upvotes: 3

K-ballo
K-ballo

Reputation: 81349

Each of your functions has a different type, so you need some kind of type erasure. You could use the most generic of them: Boost.Any. You can have a map of boost::any, but you need to know the type of the function in order to get it back and call it.

Alternatively, if you know your arguments ahead of time you can bind them with the function call and have all functions in the map be nullary functions: function< void() >. Even if you don't, you may be able to get away with it by binding the argument to references, and then at call time fill the referred variables with the appropiate arguments.

Upvotes: 1

tune2fs
tune2fs

Reputation: 7705

Can you not use the command pattern to encapsulate the function calls. So you can store the functions in functors and call them after wards. For functor implementation you can have a look at Modern C++ Design by Andrei Alexandrescu.

Upvotes: 2

vhallac
vhallac

Reputation: 13907

Why not just add functions of type int (*func)(int argc, char* argv[])? You could easily remove first arg from execute's params and call the relevant one.

Upvotes: 2

Related Questions