Put functions in a vector and execute

I want to create a vector / deque as a function container.

This deterrent must accept different functions with different arguments.

Examples of functions:

program_data::getInstance().function(int,std::string); program_data::getInstance().foo(int); program_data::getInstance().exam(int,std::string,double); 

And you can show a code example how to put these functions with arguments in std :: vector / std :: deque and execute ?

I think I should use std :: function and std :: bind, but I don't know how to support different functions with different args sizes.

With arguments -> my functions (called function foo exam from program_data ) perform some actions using arguments.

For example: I usually execute this function:

program_data::getInstance().function(10,"halo");

And now I want to put these functions in std::vector // deque and execute with the arguments that I set with the function. ie (if I put the function above on the vector and use (pseudo-code) vector[0].run(); then my program start function is program_data::getInstance().function(int,std::string); )

+6
source share
3 answers

Absolutely use std::vector<std::function<void()>> - that is, a vector of function containers with type erasure that can contain any object that can be called without arguments:

 std::vector<std::function<void()>> vector; // populate the vector vector.push_back([]{ program_data::getInstance().function(10,"halo"); }); // execute items in the vector vector[0](); 

Here I populate the vector with a bottomless lambda; you can also use lambdas with captures, bind expressions ( std::bind ) and other called objects.

If you use a lambda with a capture, you need to make sure that the captured variables are either entered by value or have a lifetime that contains a collection of calls:

 std::string tmp; vector.push_back([&tmp]{ program_data::getInstance().something(tmp); }); 
+11
source

I would suggest using std :: function and lambda expressions :

 std::vector<std::function<void()>> functions; functions.push_back([](){ program_data::getInstance().function(123, 456, "str"); }); 

This adds one function to your vector functions. By calling functions[0]() , this will call a lambda expression, which then calls your function with 123, 456 and "str" ​​as arguments.

+2
source

You can use std::function / std::bind . Therefore, first of all, you need to determine what you will transfer to these functions from the caller’s side, i.e. Define the signature of the function. The principle is the same as with virtual functions. For example, you want to pass an ordinal number (in which order functions are called) and not return anything:

 #include <vector> #include <functional> typedef std::function< void( int ) > Function; typedef std::vector<Function> Functions; void func1( int seq, const std::string &str ); void func2( const std::string &str ); void func3( int seq ); void run() { Functions functions; // populate functions functions.push_back( std::bind( func1, std::placeholders::_1, "foobar" ) ); functions.push_back( std::bind( func2, "foobar too" ) ); functions.push_back( func3 ); // you can use std::bind here as well, just to show it can be omitted if function signature matches // call them for( size_t i = 0; i < functions.size(); ++i ) { functions[i]( i ); } } 

The advantage of this method, it can be used for the pre C ++ 11 compiler with boost.

+1
source

Source: https://habr.com/ru/post/974701/


All Articles