passing a function to a function

Aug 8, 2016 at 8:38am
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 Aug 8, 2016 at 8:40am
Aug 8, 2016 at 9:07am
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 Aug 8, 2016 at 9:31am
Aug 8, 2016 at 10:17am
okay thanks im going to read about that in cpp reference.

thanks guys for the help.
Aug 8, 2016 at 2:38pm
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); }

Aug 9, 2016 at 4:54pm
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 Aug 14, 2016 at 7:52am
Aug 9, 2016 at 11:00pm
Where and how are you trying to call speedMenuHandler()?

Topic archived. No new replies allowed.