Jump to content
  • Advertisement
Sign in to follow this  
dpadam450

c++ function pointers

This topic is 1591 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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. Edited by SmkViper

Share this post


Link to post
Share on other sites


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.

Share this post


Link to post
Share on other sites

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. Edited by SeanMiddleditch

Share this post


Link to post
Share on other sites

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;
}

Share this post


Link to post
Share on other sites


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;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!