We will implement very simple string filter predicates, and then we will combine them with a little helper function that does the combination for us in a generic way.
- As always, we'll include some headers first:
#include <iostream>
#include <functional>
#include <string>
#include <iterator>
#include <algorithm>
- Because we are going to need them later, we implement two simple predicate functions. The first one tells if a string begins with the character 'a' and the second one tells if a string ends with the character 'b':
static bool begins_with_a (const std::string &s)
{
return s.find("a") == 0;
}
static bool ends_with_b (const std::string &s)
{
return s.rfind("b") == s.length() - 1;
}
- Now, let's implement a helper function, which we call combine. It takes a binary function as its first parameter, which could be the logical AND function or the logical OR function, for example. Then, it takes two other parameters, which shall be two predicate functions that are then combined:
template <typename A, typename B, typename F>
auto combine(F binary_func, A a, B b)
{
- We simply return a lambda expression that captures the new predicate combination. It forwards a parameter to both predicates and, then, puts the results of both into the binary function and returns its result:
return [=](auto param) {
return binary_func(a(param), b(param));
};
}
- Let's state that we use the std namespace to spare us some typing in the main function:
using namespace std;
- Now, let's combine our two predicate functions in another predicate function, which tells if a given string begins with a and ends with b, as "ab" does or "axxxb". As the binary function, we choose std::logical_and. It is a template class that needs to be instantiated, so we use it with curly braces in order to instantiate it. Note that we don't provide a template parameter because for this class, it defaults to void. This specialization of the class deduces all parameter types automatically:
int main()
{
auto a_xxx_b (combine(
logical_and<>{},
begins_with_a, ends_with_b));
- We iterate over the standard input and print all words back to the terminal, which satisfies our predicate:
copy_if(istream_iterator<string>{cin}, {},
ostream_iterator<string>{cout, ", "},
a_xxx_b);
cout << 'n';
}
- Compiling and running the program yields the following output. We feed the program with four words, but only two satisfy the predicate criteria:
$ echo "ac cb ab axxxb" | ./combine
ab, axxxb,