2

How would I make a function that takes address of another function as a parameter so that passing it is not necessary.

My first solution was this:

void empty_func() {}

void func(void (*additional_func) () = &empty_func)
{
    additional_func();
    // some other code...
}

This solution works.

However, I was wondering is there some more convenient way to make passing additional_function optional, so I do not have to make a new function (empty_func()) and passing it as a default argument?

JeJo
  • 30,635
  • 6
  • 49
  • 88
Kesto2
  • 70
  • 1
  • 13

3 Answers3

6

I was wondering is there some more convinient way to make passing additional_function optional so I don't have to make a new function (empty_func()) and passing it as a default argument?

You can do it by providing the default argument using curly braces:

// alias type for function pointer type
using FunPtr = void (*) (); 

void func(FunPtr additional_func = {})
//                                 ^^^
{
    if (additional_func)
       additional_func();    
       // some other code...
}

However, that leads to a nullptr check prior to the function pointer call, which makes the above not a convenient solution.

Luckily, there is an alternative. The non-capturing lambdas can be assigned to a normal function pointer type, by which we ensure there is something default to call, and thereby no null check.

using FunPtr = void (*) ();
void func(FunPtr additional_func = []{})
//                               ^^^^^^
{
    additional_func();
}
JeJo
  • 30,635
  • 6
  • 49
  • 88
3

As function pointers are also a pointer and null-equivalent for pointer types are nullptr so you can assign the value to this default parameter as nullptr.

Also, don't miss forget to add nullptr check before using it.

void func(void (*additional_func) () = nullptr )
{
    if(additional_func)
    {
        additional_func();
    }

    //some other code...
}

Also, it is more convenient to define an alias for this function-pointer as use like following:

using TPFunc = void (*) ();

void func( TPFunc additional_func = nullptr )
{
    if(additional_func)
    {
        additional_func();
    }

    //some other code...
}

But it is best to use features from functional header file instead of these raw-function-pointers. Following is an example to achieve this using functional header file:

#include <iostream>
#include <functional>
 

using TPFunc = std::function<void()>;

void func( TPFunc additional_func = nullptr )
{
    if(additional_func)
    {
        additional_func();
    }
    else
    {
        std::cout<< "Function pointer is `nullptr`\n";
    }

    //some other code...
}


void fun1()
{
    std::cout << "In 'void fun1()'\n";
}


void fun2()
{
    std::cout << "In 'void fun2()'\n";
}

int main()
{
    func();
    func(fun1);
    func(fun2);
    std::cout<< "Done";
    return 0;
}

Output:

Function pointer is `nullptr`
In 'void fun1()'
In 'void fun2()'
Done
cse
  • 4,066
  • 2
  • 20
  • 37
  • Why is it "the best to use" `std::function` instead of a pointer to function? – Kesto2 Jun 11 '23 at 10:15
  • 2
    @Kesto2, template `std::function` is just a polymorphic function wrapper. If you wants to play around raw-pointers then it is fine to use raw-function-pointers. Anyways, `std::function` don't provide a performance improvement but I'd say it is best practice to use `std::function`. One benefit which I can think of using `std::function` is that: Function call on `nullptr` instance of `std::function` will thrown `std::bad_function_call` exception. So, if you wish, you can catch the exception in your code and stop application from terminating. – cse Jun 11 '23 at 11:07
  • That's okay but I think I will stick to the raw-function-pointer for now. Considering that I just want to keep things simple. Anyways thank you for the answer. – Kesto2 Jun 11 '23 at 11:15
1

Use optional of function: std::optional<std::function<void()>> opFunc