Question:
Can an array of functions be implemented in C ++? That is, you can write the functions a()
, b()
and c()
to an array (not the functions themselves, but operators for calling them), and then call them, as it will be convenient. If not, can you call the function specified in the arguments?
Answer:
In modern c ++ there are convenient tools for operating functions as functional objects. Have a look at functional , namely std :: function and std :: bind . There are also some very good examples from the links provided.
Of course, in c ++ it is possible to work with bare pointers to functions (free and member functions of the class), but this is not so convenient and simple. Especially when building a user interface.
An example of an array of functions. We use the standard std :: vector container as an array. The following demonstrates how to use a broader definition for a narrower function signature as possible. It is known that the caller expects a signature void (int), and we will pass it void(int, int)
and void(const std::string&, int, int)
.
#include <iostream> // std::cout
#include <functional> // std::bind
#include <vector>
#include <string>
void a(int x, int y)
{
std::cout << "a(" << x << ", " << y << ")" << std::endl;
}
void b(int x, int y)
{
std::cout << "b(" << x << ", " << y << ")" << std::endl;
}
void c(const std::string& s, int x, int y)
{
std::cout << "c(" << s << ", " << x << ", " << y << ")" << std::endl;
}
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
std::vector<std::function<void(int)>> functions;
// создаем и помещаем в вектор функциональный объект, во время вызова необходимо передать один аргумент
functions.emplace_back(std::bind(a, _1, _1));
functions.emplace_back(std::bind(a, _1, 42));
functions.emplace_back(std::bind(a, _1, 100500));
functions.emplace_back(std::bind(b, _1, 42));
functions.emplace_back(std::bind(b, 42, _1));
functions.emplace_back(std::bind(c, "Hello world!", _1, 3));
int i = 0;
for (const auto& fn : functions) {
fn(i++);
}
return 0;
}
Conclusion.
a(0, 0)
a(1, 42)
a(2, 100500)
b(3, 42)
b(42, 4)
c(Hello world!, 5, 3)
Another example (taken from www.cplusplus.com ):
// bind example
#include <iostream> // std::cout
#include <functional> // std::bind
// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}
struct MyPair {
double a,b;
double multiply() {return a*b;}
};
int main () {
using namespace std::placeholders; // adds visibility of _1, _2, _3,...
// binding functions:
auto fn_five = std::bind (my_divide,10,2); // returns 10/2
std::cout << fn_five() << '\n'; // 5
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x
std::cout << fn_invert(10,2) << '\n'; // 0.2
auto fn_rounding = std::bind<int> (my_divide,_1,_2); // returns int(x/y)
std::cout << fn_rounding(10,3) << '\n'; // 3
MyPair ten_two {10,2};
// binding members:
auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
std::cout << bound_member_fn(ten_two) << '\n'; // 20
auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
std::cout << bound_member_data() << '\n'; // 10
return 0;
}