Many STL algorithms use function objects - also known as function symbols. A function character is any object that can be used in conjunction with () in a functional manner. Including function name, function pointer and class object of overload ().
For example, such a class is the function symbol
class A { private: int a; public: A(int x = 20) : a(x) {} int operator() (int b) { return a + b; } }; int main() { A temp; cout << temp(10); return 0; }
Operation results
For based on function symbol_ each,for_ The third parameter of each can accept the function pointer, but the generality is not strong. In order to improve the generality, you can pass in the template as the function symbol.
Using template function
void show(const T & t) { cout << t << " "; } int main() { int num[] = {5,2,1,3,6,9,8,7,20,10}; list <int> ls(num,num+10); //ostream_iterator<int,char> out (cout," "); for_each(ls.begin(), ls.end(),show<int>); return 0; }
You can do this by using template classes
template <typename T> class show { public: void operator()(T & t) { cout << t << " "; } }; int main() { int num[] = {5,2,1,3,6,9,8,7,20,10}; list <int> ls(num,num+10); //ostream_iterator<int,char> out (cout," "); for_each(ls.begin(), ls.end(),show<int>()); return 0; }
Operation results
STL defines the concept of function symbols
Generator: a function that can be called without parameters
Unary function: a function that can be called with one parameter
Binary function: a function that can be called with two parameters
Further
Predicate: the return value is a unary function of bool
Binary predicate: binary function whose return value is bool
You can change a template function that accepts two parameters into a template class that accepts one parameter (overload ()).
for example
template<typename T> void show(const T & t,int a) { cout << t + a << " "; } int main() { list <int> ls = {1,2,3,4,5,6,7,8,9,}; for(auto i = ls.begin();i!=ls.end();i++){ show(*(i),10); } return 0; }
Become
template<typename T> class show { private: T a; public: show(const T & x) : a(x) {} void operator()(const T & t) { cout << t + a << " "; } }; int main() { show<int> s(10); list <int> ls = {1,2,3,4,5,6,7,8,9,}; for(auto i = ls.begin();i!=ls.end();i++){ s(*(i)); } cout << endl; //or for_each(ls.begin(), ls.end(),show<int>(5)); return 0; }
Operation results
Some function symbols predetermined by C + +
For example, transform() -- it has two versions
The first version accepts four parameters. The first two parameters are iterators, representing intervals. The third parameter is an iterator pointing to where to copy. The last parameter is a function symbol, which is applied to each element.
For example, find the square root of each number and copy it to the output stream
int main() { list <int> ls = {1,2,3,4,5,6,7,8,9,}; ostream_iterator<double,char> out(cout, " "); transform(ls.begin(),ls.end(),out,sqrt<int>); return 0; }
The second version jieshou has five parameters. The first two are the same as above. The third represents the starting position of the second container, the fourth represents the iterator pointing to where to copy, and the fifth is a binary function symbol, which is applied to every two elements.
For example, sum every two elements of two containers and copy them to the output stream
template <typename T> T add(T & t1, T & t2) { return t1 + t2; } int main() { //C + + predetermined function symbol sqrt list <int> ls = {1,2,3,4,5,6,7,8,9,}; list <int> ls1 = {9,8,7,6,5,4,3,2,1}; ostream_iterator<int,char> out(cout, " "); transform(ls.begin(),ls.end(),ls1.begin(),out,add<int>); return 0; }
Operation results
The header file < functional > defines many similar template function symbols.
#include <functional> + plus - minus * multiplies / divides % modulus - negate == equal_to != not_equal_to > greater < less >= greater_equal <= less_equal && logical_and || logical_or ! logical_not
Note that they are essentially class es, only overloaded () to behave like functions.
Adaptive function operators and function adapters
Adaptive is the process of automatically adjusting the processing method, processing sequence, processing parameters, boundary conditions or constraints according to the data characteristics of the processed data in the process of processing and analysis, so as to adapt it to the statistical distribution characteristics and structural characteristics of the processed data, so as to obtain the best processing effect.
STL has five related concepts
Adaptive generator
Adaptive univariate function
Adaptive binary function
Adaptive predicate
Adaptive binary predicate
The reason for making the function symbol adaptive is that it carries typedef members that identify the parameter type and return type. These members are
result_type, first_argument_type, second_argument_type.
The meaning of function character self adaptability is that the function adapter object {can use the function object and consider that there are members of these typedef s. For example, a function that accepts an adaptive function operator parameter can use result_type member to declare a variable that matches the return type of the function.
STL provides function adapter classes that use only these tools
Suppose you want to add all the elements x2 in the container, you can use the binary function multiples, or you can use adaptive writing to generate a unary function.
Binary function
#include <functional> #include <list> #include <algorithm> #include <iterator> #include <iostream> using namespace std; int main() { multiplies<int> mul; list <int> ls = {1,2,3,4,5,6,7}; for(auto i = ls.begin();i != ls.end();i++) { *(i) = mul(*(i),2); } ostream_iterator<int,char> out (cout," "); copy(ls.begin(),ls.end(),out); return 0; }
It's obvious that we can use the function adapter (itself a template class)
binder1st -- you can create an object that can associate a value with the first parameter of a binary function, so that the object becomes a unary function
binder2nd -- same as above, but associate a value with the second value of a binary function
Because it is essentially a template class. Pay attention to instantiation when using it
Or these two functions
The same as above, but it is a function without instantiation
bind1st() -- returns a unary function symbol object
bind2nd() -- returns a unary function symbol object
So you can rewrite the code like this
int main() { list <int> ls = {1,2,3,4,5,6,7}; ostream_iterator<int,char> out (cout," "); binder1st< multiplies<int> > my_mul (multiplies<int>(),2); transform(ls.begin(), ls.end(),out,my_mul); return 0; }
Or
int main() { list <int> ls = {1,2,3,4,5,6,7}; ostream_iterator<int,char> out (cout," "); transform(ls.begin(), ls.end(),out,bind1st(multiplies<double>(),2)); return 0; }
Operation results
The two methods are slightly different, and the method of function will be simpler