std::function (C++)

Introduced to me by Kajanan, where he used it with placeholders (C++).

Resources

Why use a std::function as opposed to a raw Function Pointer?

Function pointers cannot capture context . The most evident example of this is calling a data member of an object (i.e. non-static), which you can’t do through a function pointer. Source)

  • This is because the method expects this as an implicit first argument

std::function is a versatile, type-safe wrapper for callable objects. Callable objects can be functions, lambda expressions, bind expressions, or other objects that implement the operator().

// function example
#include <iostream>     // std::cout
#include <functional>   // std::function, std::negate
 
// a function:
int half(int x) {return x/2;}
 
// a function object class:
struct third_t {
  int operator()(int x) {return x/3;}
};
 
// a class with data members:
struct MyValue {
  int value;
  int fifth() {return value/5;}
};
 
int main () {
  std::function<int(int)> fn1 = half;  // function
  std::function<int(int)> fn2 = &half; // function pointer
  std::function<int(int)> fn3 = third_t(); // function object
  // lambda expression
  std::function<int(int)> fn4 = [](int x){return x/4;};  
  // standard function object
  std::function<int(int)> fn5 = std::negate<int>();
 

How is it possible that you can pass both the function or a function pointer??

Under the hood, the function is converted into a function pointer.

#include <functional>
 
int add(int a, int b) {
    return a + b;
}
...
 
std::function<int(int, int)> func;
func = add; // assign regular function
std::cout << "Result of add: " << func(2, 3) << std::endl;
 
func = [](int a, int b) { return a * b; }; // assign lambda function
std::cout << "Result of lambda: " << func(2, 3) << std::endl;

Another example (returns void, doesn’t take in anything)

std::function<void()> f_display_42 = []() { print_num(42); };

How is this different from a function pointer? (ex: void (*func)(int, int)

std::function can hold both regular functions and lambdas.

I saw this std::forward being used in ROS codebase.