0

I have found myself to be in a situation where I need to pass a function to another function as an argument.

int callSomeFunction(int &func){
  func();
}

If it makes any difference, callSomeFunction is a class member.

class A{
  A(){}
  int callSomeFunction(int &func){
    func();
  }
  ~A(){}
};
A a();
a.callSomeFunction(func);

Ideally, callSomeFunction would be able to take any kind of function.

template<typename T>
T callSomeFunction(T &func){
  func();
}

I have tried many things to do this, Googled for several hours, all the standard stuff. I found these things but found them inconclusive as to the best way to accomplish this, or more appropriately the most efficient.

Resource 1

Resource 2

I like to use references over pointers where applicable, mostly because they are not a memory mess nor a syntactical mess in any cases. However, if pointers would be more applicable or a better solution, I welcome those answers as well. Thank you, any help or pointers on how to improve the question are also appreciated should you think it may help other people as well.

Community
  • 1
  • 1
PyroAVR
  • 719
  • 1
  • 8
  • 19
  • 1
    Show us what you've tried and why it did not work – quantdev Nov 25 '14 at 01:52
  • Also in the last line of your second snippet you don't show from where you take `func`. And when you declare `int &func` as an argument, that seems to me like a normal reference to an int, not like a function pointer ... aren't you missing parentheses here and there ? – Daniel Nov 25 '14 at 02:11
  • @quantdev, the above code is what I tried, the above notation is what should happen, but I have no idea *why* it does not work. Compiler errors point to syntax, and I am aware of function pointers, which seems to be the way to go about this. My question asks what the best way is, not "what am I doing wrong?" – PyroAVR Nov 25 '14 at 22:49
  • @DWilches, You'd be correct. It is a normal reference to an `int`, that is also what I intended. Function pointers seem like the de-facto way of going about this, but I am curious to see if there is a better way. For that matter, how do they work? – PyroAVR Nov 25 '14 at 22:53

2 Answers2

0

This is the C++-ic way to do this: (C++ needs a 'pythonic')

The standard libraries include <functional>, a header which allows you to do this easily. First, one must include <functional>, which provides std::function, std::placeholders, and std::bind.

A function has the following definition: std::function<returntype(arg1type, argNtype)> f; Unfortunately, your class or wrapper-function cannot take any kind of function, you need to know either return type or argument types, or both, of any functions you intend to use. I recommend redefining functions needed as void return type, and adding an extra argument at the end, which the output of the function sets, similar to how strcat in C works by setting the first argument equal to itself and the second argument.

void myFunction(int *arg1, float *arg2, float *returnType)

A class which could take a function defined outside of it and execute it might look something like this:

template<typename F>
class FunctionWrapper {
  std::function<void(F)> f;  //return type(argument type)
  public:
  FunctionWrapper(std::function<void(F)> _f) {
    f = std::bind(_f, std::placeholders::_1);  //makes f equal to _f, and does not specify an argument
  }
  void runFunc(F arg) {  //Now send the arguments
    f(arg);
  }
};

The line containing bind... is the most crucial. std::bind defines an std::function as another function, and can give arguments or placeholders, in the form of std::placeholders::_N. Placeholders fulfill their namesake, they allow the programmer to bind a function with arguments of unspecified type and location/value. std::bind can also be used to simplify a function by giving certain arguments as constant ahead of time, making it easier to use in the future. ie:

std::function<int(int,int,int)> simpleFunction;
simpleFunction = std::bind(rgbToHex(255, 127, std::placeholders::_1);
simpleFunction(153);

Now the programmer only has to specify the blue component.

I hope this helps anyone who is also having this issue! I need it to write a state machine class for my up-and-coming game... Please ask any questions you may have, I will clarify my answer if needed!

PyroAVR
  • 719
  • 1
  • 8
  • 19
0

C++11 supports function pointers, such that the following is valid:

int foo()
{
}

int goo()
{
}

int main()
{
    int (*pFoo)() = foo; // pFoo points to function foo()
    pFoo = goo; // pFoo now points to function goo()
    return 0;
}

So, for your case, you can pass the function pointer (pFoo in this example).

Code credit: http://www.learncpp.com/cpp-tutorial/78-function-pointers/

Baher Ramzy
  • 171
  • 6
  • function pointers have been available since C89 and C++98, not until C++11 – phuclv Dec 04 '14 at 04:42
  • Thank you! I did get this to work, however, while it is certainly the easiest way of doing this, I needed to store a function pointer (more accurately, a map of them) in a class where the type of function could not be known beforehand, hence my use of `std::function ` above. – PyroAVR Dec 05 '14 at 11:43