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