Difference between std::function<> and a standard function pointer?

C++C++11

C++ Problem Overview


Whats the difference between std::function<> and a standard function pointer?

that is:

typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);

Are they effectively the same thing?

C++ Solutions


Solution 1 - C++

A function pointer is the address of an actual function defined in C++. An std::function is a wrapper that can hold any type of callable object (objects that can be used like functions).

struct FooFunctor
{
    void operator()(int i) {
        std::cout << i;
    }
};

// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);

Here, std::function allows you to abstract away exactly what kind of callable object it is you are dealing with — you don't know it's FooFunctor, you just know that it returns void and has one int parameter.

A real-world example where this abstraction is useful is when you are using C++ together with another scripting language. You might want to design an interface that can deal with both functions defined in C++, as well as functions defined in the scripting language, in a generic way.

Edit: Binding

Alongside std::function, you will also find std::bind. These two are very powerful tools when used together.

void func(int a, int b) {
    // Do something important
}

// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.

std::function<void (int)> f = std::bind(func, _1, 5); 

In that example, the function object returned by bind takes the first parameter, _1, and passes it to func as the a parameter, and sets b to be the constant 5.

Solution 2 - C++

They are not the same at all. std::function is a complex, heavy, stateful, near-magic type that can hold any sort of callable entity, while a function pointer is really just a simple pointer. If you can get away with it, you should prefer either naked function pointers or auto-bind/auto-lambda types. Only use std::function if you really need a systematic way of organizing a heterogeneous collection of callable entities, such as functions, functors, capturing lambdas and bind expressions.


Update: A bit of explanation about auto types: Compare the following two functions:

void do_something_1(std::function<void(int)> f, int a) { f(a); }

template <typename F, typename A> void do_something_2(F f, A a) { f(a); }

Now imagine invoking them with a lambda or a bind expression:

do_something_X([foo, &bar](int n){ bar += n*foo; },     12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);

The second version with the template is more efficient, because in both cases, the argument F is deduced to the actual, unknowable type of the expression. The first version, with std::function, isn't a template and may look simpler and more deliberate, but it always forces the construction of the std::function object, and quite possibly carries multiple type erasure and virtual dispatch costs.

Solution 3 - C++

A std::function has state. It can hold additional parameters "bound" into it.

These parameters can range from things like other classes, other functions, or even this pointers for member function calls.

The replacement function pointer is not typedef int (*fn)(int);

It is typedef int (*fn)(void*,int);, with the void* reperensting the state that would be hidden in the std::function.

Solution 4 - C++

No.

One is a function pointer; the other is an object that serves as a wrapper around a function pointer.

They pretty much represent the same thing, but std::function is far more powerful, allowing you to do make bindings and whatnot.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaCuriaView Question on Stackoverflow
Solution 1 - C++Paul MantaView Answer on Stackoverflow
Solution 2 - C++Kerrek SBView Answer on Stackoverflow
Solution 3 - C++user406009View Answer on Stackoverflow
Solution 4 - C++Lightness Races in OrbitView Answer on Stackoverflow