This is powerful way to represent predicator.
Let's see how to use it.
First, I show a sample with no 'std::function's.
// Predicator class(i.e., has operator() ) which take int for argument and returns int by adding it's internal value.
class Adder
{
public:
int to_add;
int operator()(int a) {
return a + to_add;
}
};
// Another predicator doing multiply.
class Multiplier
{
public:
int to_mul;
int operator()(int a) {
return a * to_mul;
}
};
// Some class having std::vector<int>
class Foo
{
std::vector<int> vec;
public:
// apply predicator.
template <typename T>
void apply(T pred) {
for(int& elm : vec) {
elm = pred(elm); //the predicator is intended to have 'int operator(int)'
}
}
};
// some function
void Bar(Foo& foo, int to_add, int to_mul)
{
Adder adder;
adder.to_add = to_add;
foo.apply(adder); // add for each int
Multilier multi;
multi.to_mul = to_mul;
foo.apply(multi); // mulply for each int
}
We need to declare predicator class for each calcuration( adding and multipling )
Next, let's do this using std::function.
// Some class having std::vector<int>
class Foo
{
std::vector<int> vec;
public:
// apply predicator.
void apply(std::function<int(int)> func) { //take std::function which take int as argument, and returns int.
for(int& elm : vec) {
elm = func(elm); // call the func
}
}
};
int add(int a, int to_add) { return a+to_add; }
int mul(int a, int to_mul) { return a*to_mul; }
void Bar(Foo& foo, int to_add, int to_mul)
{
//std::bind() makes std::function instance holding function pointer with internal values.
//std::placeholders::_1 means the argument will passed by caller.
std::function<int(int)> adder = std::bind(&add, std::placeholders::_1, to_add);
//so, 'adder' has a pointer to function 'add' and a value 'to_add'.
//first argument will be passed by the caller.
foo.apply(adder); // add 2 for each int
//std::function to multiply.
std::function<int(int)> multi = std::bind(&mul, std::placeholders::_1, to_mul);
foo.apply(multi); // mulply 3 for each int
}
std::function can have any value in it. and has operator() of specified type signature.
for example,
std::function<int(float)> - function object that take float for arugment, returns int. std::function<std::string(double, int)> - function object that take double and int, returnts std::string
Next, let's make this example shorter with lambda expression.
// Some class having std::vectorclass Foo { std::vector<int> vec; public: // apply predicator. void apply(std::function<int(int)> func) { //take std::function which take int as argument, and returns int. for(int& elm : vec) { elm = func(elm); // call the func } } }; void Bar(Foo& foo, int to_add, int to_mul) { // lambda expression can make function object in line. std::function<int(int)> adder = [to_add](int a) -> int { return a+to_add; }; foo.apply(adder); // add 2 for each int std::function<int(int)> multi = [to_mul](int a) -> int { return a*to_mul; }; foo.apply(multi); // mulply 3 for each int }
With std::function, we can easily declare predicator and make the program more flexible.
No comments:
Post a Comment