2

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> ...
2
  • How are you going to execute if the map could have a int functionA(int) and a void functionC(const std::string&)? You need some level of uniformity in the declarations to have them at all usable, so you might as well just pick a standard flexible declaration, like in @vhallac's answer. Commented Oct 20, 2011 at 21:38
  • In your code, what if argc>1 is true but you pass and call functionB, which accept no parameter? Maybe you should consider the Strategy Design Pattern instead, where you implement different algorithms with "functors" and you can select them at runtime, like you are doing in your function execute() Commented Oct 20, 2011 at 21:43

5 Answers 5

3

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();
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

I believe casting function pointers to void* is non standard.
boost::function is not a pointer, and does not use the dereference operator (plus, you don't dereference function pointers either).
Good point with the edit. Much better than trying to cram unrelated types into a single map.
@CatPlusPlus, I haven't used boost::function, I was just going by the submitter's syntax.
@ Tim, yes I thought of this, but I was wondering if there was a more general approach :)
|
3

You can use

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

Comments

2

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.

3 Comments

because I want to access functions which are already coded (see my edit)
@Smash You could make a new set of functions that act as a bridge between existing function and execute. Their job would be to read and parse relevant arguments, and call the other functions. This is a very C way of doing things, but it separates the concerns quite well.
true, but it's almost defeating the purpose, I should just do if else else else etc..
2

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.

Comments

1

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.

2 Comments

I like the idea of the 2nd part, I'll give it a try
ok, but then how can I be able to retrieve the type of the parameter that was bound to the function when i want to execute it, this information seems to have been lost

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.