What if you want to accumulate all elements in a container?
The accumulate of STL allows us to write loops by ourselves:
# Include <iostream>
# Include <functional>
# Include <numeric>
# Include <vector>
# Include <string>
Int main ()
{
Std: vector <int> vect;
Vect. push_back (1 );
Vect. push_back (2 );
Vect. push_back (3 );
Vect. push_back (4 );
Std: cout <"Accumulate:" <
Std: accumulate (vect. begin (), vect. end (), 0, std: plus <int> ());
}
Output:
Accumulate: 10
Std: plus <int> () can be omitted, because it is the default action of the three parameters. Note that the accumulate algorithm is defined in numeric instead of algorithm.
Because both accumulate and plus are generic, if you want to accumulate a string instead of an int, the modification to the program is not great:
# Include <iostream>
# Include <functional>
# Include <numeric>
# Include <vector>
# Include <string>
Int main ()
{
STD: vector <STD: String> vect;
Vect. push_back ("1 ");
Vect. push_back ("2 ");
Vect. push_back ("3 ");
Vect. push_back ("4 ");
STD: cout <"accumulate:" <
STD: Accumulate (vect. Begin (), vect. End (), STD: string (""));
}
Output:
Accumulate: 1234
However, if boost. Lambda is used, there will be some nice-looking and easy-to-understand solutions to this problem:
# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <vector>
# Include <string>
# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>
// # Include <boost/bind. hpp>
Using namespace boost: lambda;
// Using namespace boost;
Int main ()
{
Std: vector <std: string> vect;
Vect. push_back ("1 ");
Vect. push_back ("2 ");
Vect. push_back ("3 ");
Vect. push_back ("4 ");
Std: string result;
Std: for_each (vect. begin (), vect. end (), result + = _ 1 );
Std: cout <result;
}
Output:
1234
Here we need to borrow the variable result. There are several more lines in this program, but the purpose of calling accumulate is to put the result into a variable. In this way, boost is used. lambda looks pretty.
In the above program, another ugly thing is vector initialization. In order to put 1, 2, 3, and 4 in vect, we have to call push_back four times! However, using boost. lambda is much better.
Std: vector <int> vect (10 );
Int I = 0;
Std: for_each (vect. begin (), vect. end (), _ 1 = ++ var (I ));
There are two points worth noting:
1. You must specify the size in the vect statement. Otherwise, for_each will not do anything for an empty container.
2. You must use ++ var (I) instead of ++ I. The role of var here is to force lazy evaluation, that is, to evaluate the variable when it is used. If ++ I is used, you will get a vect with 10 values, instead of 1-10.
========================================================== ========================================================== =
Many problems will be complicated when it comes to map. What should we do if we want to accumulate all the keys or values in a map? At this time, you cannot directly use accumulate. You can use boost. bind to do this:
# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>
# Include <boost/bind. hpp>
Using namespace boost;
Int main ()
{
Std: map <int, std: string> persons;
Persons [2, 123] = "Amy ";
Persons [234] = "Ralph ";
Persons [1, 345] = "Simon ";
Persons [1, 456] = "Maggie ";
Std: cout <std: accumulate (persons. begin (), persons. end (), 0,
Bind (std: plus <int> (), _ 1, bind (& std: map <int, std: string >:: value_type: first, _ 2 )))
<Std: endl;
Std: cout <std: accumulate (persons. begin (), persons. end (), std: string (),
Bind (std: plus <std: string> (), _ 1, bind (& std: map <int, std: string >:: value_type: second, _ 2 )))
<Std: endl;
}
Output:
1158
AmyRalphSimonMaggie
But in all fairness, it is not really beautiful. Continuous bind is not more dizzy than self-written loops. Boost. lambda also uses bind, but it can be much clearer:
# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>
# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>
Using namespace boost: lambda;
Int main ()
{
Std: map <int, std: string> persons;
Persons [2, 123] = "Amy ";
Persons [234] = "Ralph ";
Persons [1, 345] = "Simon ";
Persons [1, 456] = "Maggie ";
Int iresult = 0;
Std: string sresult;
Std: for_each (persons. begin (), persons. end (),
Iresult + = bind (& std: map <int, std: string >:: value_type: first, _ 1)
);
Std: for_each (persons. begin (), persons. end (),
Sresult + = bind (& std: map <int, std: string >:: value_type: second, _ 1)
);
Std: cout <iresult <std: endl;
Std: cout <sresult <std: endl;
}
The output is the same as the above:
1158
AmyRalphSimonMaggie
With its help, it will not be too difficult to add another layer of indirect layers: If your map does not directly store strings, but stores the Person object, their names must be obtained through the Name () method, and the code only needs to be slightly modified:
# Include <iostream>
# Include <algorithm>
# Include <numeric>
# Include <map>
# Include <string>
# Include <boost/lambda. hpp>
# Include <boost/lambda/bind. hpp>
Using namespace boost: lambda;
Class Person
{
Public:
Person (){}
Person (const std: string & name): name _ (name ){}
Std: string & Name ()
{Return name _;}
Private:
Std: string name _;
};
Int main ()
{
Std: map <int, Person> persons;
Persons [1, 123] = Person ("Amy ");
Persons [234] = Person ("Ralph ");
Persons [1, 345] = Person ("Simon ");
Persons [1, 456] = Person ("Maggie ");
Std: string result;
Std: for_each (persons. begin (), persons. end (),
Result + = bind (& Person: Name, bind (& std: map <int, Person >:: value_type: second, _ 1 ))
);
Std: cout <result;
}
Output:
AmyRalphSimonMaggie