c++ function pointers

Started by
23 comments, last by Pink Horror 9 years, 9 months ago
I meant the syntax. But a good summary anyway.
Advertisement

I must prefer functors. Don't have to deal with any extra weird syntax. Plus, they can store data.

Functors and function pointers both have their uses.

If you're writing a non-generic function that needs to refer to another function, use std::function:

void foo(std::function<int(float)> func) {
  int output = func(12.34f);
}
If you're writing a generic (templated) function, you can either continue to use std::function or use a template type:

template <typename Callable>
void foo(Callable&& func) {
  int output = func(12.34f);
}
The second form is a little worse in some ways because it lets you pass anything in to the function and you get the usual terrible template errors, but it's mildly more efficient in some cases on some compilers with some optimization flags on some versions. Just use std::function unless you have hard evidence (e.g. analyzed profiling data) that you need something else.

Sean Middleditch – Game Systems Engineer – Join my team!

Functors and function pointers both have their uses.

If you're writing a non-generic function that needs to refer to another function, use std::function:







void foo(std::function<int(float)> func) {
  int output = func(12.34f);
}
If you're writing a generic (templated) function, you can either continue to use std::function or use a template type:


template <typename Callable>
void foo(Callable&& func) {
  int output = func(12.34f);
}
The second form is a little worse in some ways because it lets you pass anything in to the function and you get the usual terrible template errors, but it's mildly more efficient in some cases on some compilers with some optimization flags on some versions. Just use std::function unless you have hard evidence (e.g. analyzed profiling data) that you need something else.


Might I ask why you are using a templated r-value reference (aka "universal reference") in your template example and not a const ref? Foo is not "sinking" the parameter and simply invokes the () operator on it.

Of course, if you were going to take func and stick it by value into a class member or something similar using std::forward then I could see why you'd do that.

Also, my personal experience (backed up with profiling data on the compilers I use) is that the templated version always produces better, or at least equivalent, code to std::function, and you don't have to worry about hidden allocations and copies of large function objects (i.e. lambdas with several capture variables). For example, std::function on one library has 3 pointers worth of data storage for small-block-optimization, while another library has 4 pointers worth of data storage. If your lambda is larger then that, the library has to allocate space for std::function, where it doesn't have to for the template.

So I end up using the templated version wherever possible, and std::function when I have to - usually because I'm storing the function in a class variable, or the function pointer is passed to a virtual function that may be overridden.


Might I ask why you are using a templated r-value reference (aka "universal reference") in your template example and not a const ref? Foo is not "sinking" the parameter and simply invokes the () operator on it.

In this case it might not be necessary to use a universal reference, but if foo called another function and wanted to pass along func, then it could do so with perfect forwarding.

Might I ask why you are using a templated r-value reference (aka "universal reference") in your template example and not a const ref? Foo is not "sinking" the parameter and simply invokes the () operator on it.


A const reference would bar the functor from having mutable state, imposing an unnecessary rule upon it. Universal references are a good default choice if you don't have a strong reason to prefer an lvalue reference, value, or const reference.

Sean Middleditch – Game Systems Engineer – Join my team!

8 Years never needed a function pointer and I can't find a good example.

I find The Function Pointer Tutorials to be a good resource. Pros: an easy read, has examples, talks about functors. Cons: old, doesn't cover std::function.

I second SiCrane, If you want to know what it would look like without typedefs, though:


int AddOne(int a)
{
    return a + 1;
}

int (*GiveMeFunctionPointer())(int)
{
    return &AddOne;
}
Function pointer types are weird. It sort of goes around the function declaration.


In the "new" standard (C++11), you can use a type alias instead of typedef:


using PF = int(*)(int);

Or, without typedef or alias, C++11 allows trailing return types; the syntax may be somewhat clearer:


auto GiveMeFunctionPointer() -> int (*)(int)
{
    return &AddOne;
}

I find The Function Pointer Tutorials to be a good resource. Pros: an easy read, has examples, talks about functors. Cons: old, doesn't cover std::function.

Also missing: lambdas, mem_fn, bind. In modern C++, especially lambdas are a "must know", IMO.


Or, without typedef or alias, C++11 allows trailing return types; the syntax may be somewhat clearer:

C++14 makes this even cleaner:


auto GiveMeFunctionPointer()
{
    return &AddOne;
}

This topic is closed to new replies.

Advertisement