• Advertisement
Sign in to follow this  

c++ function pointers

This topic is 1316 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

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

#include <iostream>
using namespace std;

// Basic Function
int AddOne(int a)
{
    return a + 1;
}

// I want a function that returns a pointer to AddOne so I can call it

// This declaration does not work, what is the delcaration to return the function as a pointer.
int (*)(int) GiveMeFunctionPointer()
{
    return &AddOne;
}

void main()
{
    int (*foo)(int) = &AddOne; // Cool foo is a pointer to a function taking an int

    int (*foo2)(int) = GiveMeFunctionPointer(); // This is what I want to use...

    cout << foo(2);
    system("pause");
}

Edited by dpadam450

Share this post


Link to post
Share on other sites
Advertisement

Going to apply that to my actual code now..........does anyone know what that actually unrolls into? I don't mind typdef's for this case, I just hate typdef everything to a typdef item with a a typdef vector etc. I usually avoid them for readability.
 

// Obviously this doesnt work. Just curious what the signature without the typdef would be
int (*function_type)(int) GiveMeFunctionPointer()

{

}

 

Thanks.

Share this post


Link to post
Share on other sites

 

Function pointer types are weird. It sort of goes around the function declaration.

I did try something like that I guess I didnt have it correct. Either way typdef has worked in my engine. Sweet.

Share this post


Link to post
Share on other sites


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

 

Function pointers are kind of a weird tool in your toolbox. People are normally taught function pointers in an academic/abstract setting and then they are quickly forgotten because you can get by without them on a day to day basis. So here is a real world example.

 

I recently used function pointers (C# delegates) in a generic Credit Card Processing library that I wrote for my employer. It needed to work across all the C# projects who had different data-layers. I had a very specific series of events I wanted to happen when sending a credit card transaction as it was being used to make it bullet proof.

  1. Save the credit card transaction attempt BEFORE sending to the processor - Status: About to Send
  2. Send the transaction to the processor
  3. Save the result of the credit card transaction - Status: Approved/Denied

I could have solved this problem with documentation. Hey jerkies! Do it like I told you! But, if they didn't use it correctly, the burden of figuring out the problem was going to be on my shoulders anyway. So I'd rather be sure.

 

I could have solved the problem with direct saves through one of the data layers. But then I'd have to copy/paste the code in each project and rewrite the saves for each data layer. If there was a bug, I'd have to fix it in each copy of the code... Bleh.

 

So, I decided to use function pointers (C# delegates). The signature was:

bool PersistTransaction(CreditCardTransactionInfo)

I didn't care how they saved it, I just tell them the info they need to save. If there is a problem saving the data, they should return false to me so I don't try to go through with the transaction. This allowed them to use the data layer they felt like using. Heck, they could have even saved it to a file instead of into the database if they felt like it.The more junior programmers started murmuring amongst themselves and claimed I was a dark sorcerer...

 

In games, you might use function pointers to control simple AI movements for sidescrolling shooters. Basic enemies might just move straight, others might follow a sin curve, and others track the player like a heat seeking missile. You can solve this problem without function pointers, but it opens up some neat possibilities.

 

- Eck

Share this post


Link to post
Share on other sites

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

I always found std::function to be the easiest way to deal with function pointers.  The biggest benefit is the easy use of multiple types of function like objects, including lambdas (which I find surprisingly fun to use...).  I think you will find the syntax easier to use, and it seems easier to understand than raw function pointers.

Share this post


Link to post
Share on other sites

I have actually used function references too, for the same reasons you'd use references over pointers to variables.

Share this post


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

  • Advertisement