We use count_if when we want to get the number of elements in a sequence that respect a clause we specify; find_if is used to find the fist element in a sequence matching our requirements.
Without using boost or C++11 we should define a functor to specify the behavior that we are interested in. As we can see in this example, the new techniques make the code cleaner and more readable:
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <iterator> #include "boost/bind.hpp" using namespace std; namespace { template<class T> void dump(vector<T>& vec) { copy(vec.begin(), vec.end(), ostream_iterator<T>(cout, " ")); cout << endl; } } void bind04() { vector<int> vec; vec.push_back(12); vec.push_back(7); vec.push_back(4); vec.push_back(10); dump(vec); cout << endl << "Using boost::bind" << endl; cout << "Counting elements in (5, 10]: "; // 1 auto fb = boost::bind(logical_and<bool>(), boost::bind(greater<int>(), _1, 5), boost::bind(less_equal<int>(), _1, 10)); int count = count_if(vec.begin(), vec.end(), fb); cout << "found " << count << " items" << endl; cout << "Getting first element in (5, 10]: "; vector<int>::iterator it = find_if(vec.begin(), vec.end(), fb); if(it != vec.end()) cout << *it << endl; cout << endl << "Same, but using lambda expressions" << endl; cout << "Counting elements in (5, 10]: "; // 2 auto fl = [](int x){ return x > 5 && x <= 10; }; count = count_if(vec.begin(), vec.end(), fl); cout << "found " << count << " items" << endl; cout << "Getting first element in (5, 10]: "; it = find_if(vec.begin(), vec.end(), fl); if (it != vec.end()) cout << *it << endl; }1. since we use the same predicate a couple of times it's a good idea storing it in a local variable (here using the cool C++11 'auto' keyword to save the time from figuring out the correct type definition for the predicate). The construct is a bit verbose, but should be clear enough in its sense: we are looking for a value in the interval (5, 10]; count_if will count all the elements in the sequence respecting this rule; find_if will return the iterator to the first element for which that is valid - or end() if no one will do.
2. it is so much cleaner implementing the same functionality using the C++11 lambda syntax.
The code is based on an example provided by "Beyond the C++ Standard Library: An Introduction to Boost", by Björn Karlsson, an Addison Wesley Professional book. An interesting reading indeed.
No comments:
Post a Comment