Understand C++ programming std::function function encapsulation

  • 2020-05-09 19:02:46
  • OfStack

Take a look at the following two lines of code:


std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed;
std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased;

These two lines of code are taken from Cocos2d-x. The key is the definition of these two lines of code. What is std::function? If you're comfortable with the above two lines of code, take a second look at this article and learn something new.

std: : function is introduced
std::function is a generic, polymorphic encapsulation of functions. Instances of std::function can store, copy, and invoke any target entity that can be called, including normal functions, Lambda expressions, function Pointers, and other function objects. The std::function object is a type-safe package for existing callable entities in C++ (we know that callable entities such as function Pointers are type-unsafe).

In general, std::function is a function object class, which wraps any other function object. The wrapped function object has the type T1,... ,TN's N parameters, and returns a value that can be converted to R. std::function receives wrapped function objects using the template transformation constructor; In particular, the closure type can be implicitly converted to std::function.

The simplest way to think about it is:

Through the encapsulation of various callable entities (ordinary functions, Lambda expressions, function Pointers, and other function objects) in C++ by std::function, a new callable std::function object is formed. Let's not worry about so many callable entities. 1. Shear is simple and rough.
Easy to use and practical things will be added to the standard. We use it in projects because it's easy to use and useful. std::function implements a set of type elimination mechanisms that can be used to handle different types of function objects. We used to use function Pointers to do this; Now we can use the more secure std::function to do these tasks.

The sample


#include <functional>
#include <iostream>
 
struct Foo {
  Foo(int num) : num_(num) {}
  void print_add(int i) const { std::cout << num_+i << '\n'; }
  int num_;
};
 
void print_num(int i)
{
  std::cout << i << '\n';
}
 
struct PrintNum {
  void operator()(int i) const
  {
    std::cout << i << '\n';
  }
};
 
int main()
{
  //  Save free function 
  std::function<void(int)> f_display = print_num;
  f_display(-9);
 
  //  save  lambda  expression 
  std::function<void()> f_display_42 = []() { print_num(42); };
  f_display_42();
 
  //  save  std::bind  The results of the 
  std::function<void()> f_display_31337 = std::bind(print_num, 31337);
  f_display_31337();
 
  //  Save member function 
  std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
  Foo foo(314159);
  f_add_display(foo, 1);
 
  //  Save member functions and objects 
  using std::placeholders::_1;
  std::function<void(int)> f_add_display2= std::bind( &Foo::print_add, foo, _1 );
  f_add_display2(2);
 
  //  Save member functions and object Pointers 
  std::function<void(int)> f_add_display3= std::bind( &Foo::print_add, &foo, _1 );
  f_add_display3(3);
 
  //  Save the function object 
  std::function<void(int)> f_display_obj = PrintNum();
  f_display_obj(18);
}

Output:


-9
42
31337
314160
314161
314162
18


Related articles: