Question

I've been looking into how to pass a function as a parameter to another function in C++.

I'm not sure I understand the terminology correctly so I haven't found exactly what I'm looking for online. I thought I could better explain it as a question.

I'm trying to pass a function as an argument which takes place at a certain point in the function it's passed too.

Here's some pseudo-code to better explain my query:

    myNewFunction( passedFunction_1, passedFunction_2 ){

            //do some magic in OpenGL
                execute passedFunction_1
            //do some magic in OpenGL
                execute passedFunction_2
            //do some magic in OpenGL
                execute passedFunction_1 (again)
            //do some magic in OpenGL
    }

I hope you understand. Any help would be appreciated. Thanks in advance.

Was it helpful?

Solution

Since we're talking about C++ and not C, you should use std::function. It's safer, and you can also use it to do more complex things like testing for existence, binding / currying...

#include <iostream>
#include <functional>

#using namespace std;

typedef function<void (void)> tVoidFunction;
typedef function<void (int)> tVoidFunctionTakingIntParameter;
typedef function<int (float)> tIntFunctionTakingFloatParameter;

void combinedFunction( tVoidFunction fvoid, tVoidFunctionTakingIntParameter fInt, tIntFunctionTakingFloatParameter fIntFromFloat){
  if (fvoid) {
    fvoid();
  }
  if (fInt && fIntFromFloat) {
    static const float magicValue = 42.f;
    int convertedValue = fIntFromFloat(magicValue);
    fInt(convertedValue);
  }
}

void helloWorld() {
  cout << "Hello World" << endl;
}
int floatToInt(float f) {
  return floor(abs(f));
}
void doSomethingWithAnInt(int i) {
  cout << "doSomethingWithAnInt: " << i << endl;
}
...

void doWeirdThings() {
  combinedFunction(helloWorld, doSomethingWithAnInt, floatToInt);
}

Ho illustrate why this is better than C-style function pointers, here are a couple (somewhat contrived) examples using std::bind and a lambda to do some more interesting functional stuff:

struct Foo {
  void doSomethingWithAnInt(int i) {
    cout << "Foo instance @" << this << " got: " << i << endl;   
  }
}
int doSomethingWithTwoFloats(float f1, float f2) {
   return floor(sqrt(abs(f1 + f2)));
}

...

void doWeirderThingsThanBefore() {
  Foo someFoo;
  auto someFooDoesSomethingWithAnInt = bind(&Foo:doSomethingWithAnInt, &someFoo);
  static const float anotherMagicValue = 69.f;
  auto doSomethingWithTheMagicValue = bind(&doSomethingWithTwoFloats, anotherMagicValue);
  auto helloLambda = [](){
    cout << "Hello, Lambda!" << endl;
  };

  combinedFunction(helloLambda, someFooDoesSomethingWithAnInt, doSomethingWithTheMagicValue);
}

OTHER TIPS

The latest standard defines a std::function class for doing exactly this, and is probably the easiest approach (especially considering the perhaps intimidating syntax of C function pointers).

The syntax would be something like:

myNewFunction( std::function<void()> passedFunction_1, std::function<void()> passedFunction_2 ){
        //do some magic in OpenGL
            passedFunction_1();
        //do some magic in OpenGL
            passedFunction_2()
        //do some magic in OpenGL
            passedFunction_1();
        //do some magic in OpenGL
}

Instantiating a std::function is done by identifying the function that you're wanting to pass around, just as you would if you were using raw C function pointers (one of the nice things about std::function is that it plays so nicely with C function pointers). Something like the following:

void do_stuff(std::function<void()> another_function)
{
    // Doing stuff

    another_function(); // Invoking the parameter
}

void something_extra()
{
    // Does something else
}

int main()
{
    std::function<void()> the_function = &something_extra;

    // Invoke do_stuff, with something_extra as the function being passed in
    do_stuff(the_function);

    return 0;
}

Define myNewFunction so that it takes two other functions. passFunction1 as well as passFunction2 are pointers to functions that expect no arguments and return nothing.

void myNewFunction(void (*passFunction1)(),
                   void (*passFunction2())
{
    passFunction1();
    passFunction2();
    passFunction1();
}

Define a function that takes no arguments, does somethings, and returns nothing.

void foo()
{
   // Do something useful
}

Define another function that takes no arguments, does somethings, and returns nothing.

void bar()
{
   // Do something useful
}

Call the first function using the last two functions.

myNewFunction(foo, bar);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top