46

What is the advantage of std::function<T1(T2)> over the original T1 (*)(T2)?

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71

3 Answers3

37

std::function can hold more than function pointers, namely functors.

#include <functional>

void foo(double){}

struct foo_functor{
  void operator()(float) const{}
};

int main(){
  std::function<void(int)> f1(foo), f2((foo_functor()));
  f1(5);
  f2(6);
}

Live example on Ideone.

As the example shows, you also don't need the exact same signature, as long as they are compatible (i.e., the parameter type of std::function can be passed to the contained function / functor).

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 4
    Also, with `std::bind` it is possible to create delegates (i.e. encapsulate a member function pointer with an object) and store them in an std::function, without any difference in handling after creation. This is something that function pointers alone are not capable of. – Tamás Szelei Jul 05 '12 at 21:47
  • 2
    @fish: Well, what `std::bind` returns is a functor, so I wouldn't really special-case that. What can be seen as special is that you can just pass a member function pointer and the `std::function` will make it callable like `f(object, param);`. [Example on Ideone](http://ideone.com/haRtx) – Xeo Jul 05 '12 at 21:49
  • 1
    Another thing is (arguably) easier declarations. Function pointer declarations are a little hard follow due to their C heritage of *"declaration reflecting usage"*-rule. `std::function` objects have a declaration that looks more like a function declaration. (sorry I really should make an edit, but I see that the post is still being updated frequently at this moment. feel free to merge in these). – Tamás Szelei Jul 05 '12 at 21:50
  • yeah, well of course it does. I think it is worth mentioning because delegates are a common pattern in many languages and this is what makes it possible to fluidly replicate them in C++. – Tamás Szelei Jul 05 '12 at 21:52
  • As it is, the program compiles but doesn't do anything. Can I suggest to `cout` the argument in both the function and the functor? And I'd also add a call using a non-integer argument, like `f1(4.7);`. This would show the effect of storing a function accepting a `double` into an `std::function` accepting an `int` parameter. I would also include the output into the answer. I've already prepared the modified code [on Ideone](https://ideone.com/PD9rwW). I can edit your answer myself, if you agree, but I'll do it only with your permission. – Fabio says Reinstate Monica Mar 12 '19 at 12:59
17

std::function can hold function objects (including lambdas), as well as function pointers with the correct signature. So it is more versatile.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
11

Apart from the cleaner look and a more descriptive syntax, std::function can store any callable object:

  • functions
  • lambda expressions
  • bind expressions
  • functors

Not to mention that storing, copying, and binding objects to member functions is much easier and more intuitive.

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71
Shoe
  • 74,840
  • 36
  • 166
  • 272