passing a function to a function

is it possible in C++ to pass a function to one another to perform its task?

i mean like this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void task()
{
   //do something
}
void task2()
{
   //do something
}
void dotask(void v())
{
   for ( int a = 0; a < 10; a++ )
   {
       v();
   }
}

int main()
{
    if ( true )
    {
        dotask(task());    
    }
    else 
    {
        dotask(task2());
    }
}


if i do this manually, i will have a duplicate codes
Last edited on
Instead of using the "outdated" method of passing functions I would recommend using std::function instead.

For example here is closed account's example rewritten to use std::function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <functional>

void task()
{
   std::cout << "Task" << std::endl;
}

void task2()
{
   std::cout << "Task2" << std::endl;
}

void doTask(std::function<void()> func)
{
   for ( int a = 0; a < 10; a++ )
   {
       func();
   }
}

int main()
{
    if (true)
    {
        dotask(task);    
    }
    else 
    {
        dotask(task2);
    }
    
    return 0;
}


Now you might ask why use std::function when using a C function pointer works also? Well there is quite a few benefits actually. First of all std::function works with more then just function pointers, it works with any callable object which include

- Functors
- Lambdas
- Functions
- std::bind expressions

For example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <functional>

struct testFunctor
{
  void operator()() const { std::cout << "Testing..." << std::endl; }
};

void doTask(std::function<void()> func)
{
   for ( int a = 0; a < 10; a++ )
   {
       func();
   }
}

int main()
{
    doTask(testFunctor());
    
    return 0;
}


If you tried using a functor with a C function pointer you would be out of luck as far as I know.


Another benefit of using std::function would be that it is much cleaner looking code and you can determine more quickly what type of function it is looking for. For example std::function<void (int, int)> someFunc; compared to void (func*)(int, int). For me it is much easier to tell that it wants a function that returns void and has two integer parameters in the std::function object then it is with a C function pointer.

And lastly when using std::function it is much easier to work with storing and using members functions. There is a few more features that std::function and it's helpers provide but they need a bit more in-depth discussion to explain so will leave that for you to research.
Last edited on
okay thanks im going to read about that in cpp reference.

thanks guys for the help.
For what it's worth, the only error in your original code was an extra pair of paretheses in the call: it's dotask(task);, not dotask(task());

For a more complete list of options, you can pass a function
1. by reference
1
2
3
void dotask(void (&v)()) { v(); }
void task() {}
int main() { dotask(task); }

2. by pointer
1
2
3
void dotask(void (*v)()) { v(); }
void task() {}
int main() { dotask(task); }

3. by pointer using decay (just like when you write f(int[]), you get f(int*)
1
2
3
void dotask(void v()) { v(); }
void task() {}
int main() { dotask(task); }

4. using std::function mentioned above
1
2
3
4
#include <functional>
void dotask(std::function<void()> v) { v(); }
void task() {}
int main() { dotask(task); }

5. as a generic callable parameter
1
2
3
4
template<class F>
void dotask(F v) { v(); }
void task() {}
int main() { dotask(task); }

hello guys,

i cant get it to work using std::function

my compiler keeps saying this error

no matching function for call to 'Menu::speedMenuHandler(<unresolved overloaded function type>)'|

heres my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Menu
{
        void speedMenuHandler(std::function<void(std::size_t)>);
        void test1(std::size_t a);
        void run();
}
void Menu::run()
{
     speedMenuHandler(test1);
}
void Menu::speedMenuHandler(std::function<void(std::size_t)> task)
{
        for ( std::size_t a = 0; a < speedLevels.size(); a++ )
        {
            task(a);
        }
}


        void Menu::test1(std::size_t a)
        {
            if ( isHovered(speedLevels[a]) )
            {
                Game::setGameSpeed(static_cast<Game::speed>(a));
                menuState = DEFAULT;
            }
        }

Last edited on
Where and how are you trying to call speedMenuHandler()?

Topic archived. No new replies allowed.