As another example, let’s count the number of elements in the sequence not equal to 20. This time we’ll use the algorithm count_if( ), introduced earlier. There is a standard binary function object, equal_to, and also a function object adapter, not1( ), that take a unary function object as a parameter and invert its truth value. The following program will do the job.
//: C06:CountNotEqual.cpp
// Count elements not equal to 20
#include
#include
#include
#include
using namespace std;
int main() {
int a[] = {10, 20, 30};
const size_t SIZE = sizeof a / sizeof a[0];
cout << count_if(a, a + SIZE,
not1(bind1st(equal_to
} ///:~.
As remove_copy_if( ) did in the previous example, count_if( ) calls the predicate in its third argument (let’s call it n) for each element of its sequence and increments its internal counter each time true is returned. If, as before, we call the current element of the sequence by the name e, the statement.
if (n(e))
in the implementation of count_if is interpreted as
if (!bind1st(equal_to
which of course ends up as
if (!equal_to
because not1( ) returns the logical negation of the result of calling its unary function argument. The first argument to equal_to is 20 in this case because we used bind1st( ) instead of bind2nd( ). Since testing for equality is symmetric in its arguments, we could have used either bind1st( ) or bind2nd( ) in this example.
The following table shows the templates that generate the standard function objects, along with the kinds of expressions to which they apply.
Name | Type | Result produced |
---|---|---|
plus | BinaryFunction | arg1 + arg2 |
minus | BinaryFunction | arg1 - arg2 |
multiplies | BinaryFunction | arg1 * arg2 |
divides | BinaryFunction | arg1 / arg2 |
modulus | BinaryFunction | arg1 % arg2 |
negate | UnaryFunction | - arg1 |
equal_to | BinaryPredicate | arg1 == arg2 |
not_equal_to | BinaryPredicate | arg1 != arg2 |
greater | BinaryPredicate | arg1 > arg2 |
less | BinaryPredicate | arg1 < arg2 |
greater_equal | BinaryPredicate | arg1 >= arg2 |
less_equal | BinaryPredicate | arg1 <= arg2 |
logical_and | BinaryPredicate | arg1 && arg2 |
logical_or | BinaryPredicate | arg1 || arg2 |
logical_not | UnaryPredicate | !arg1 |
unary_negate | Unary Logical | !(UnaryPredicate(arg1)) |
binary_negate | Binary Logical | !(BinaryPredicate(arg1, arg2)) |
Adaptable function objects
Standard function adapters such as bind1st( ) and bind2nd( ) make some assumptions about the function objects they process. To illustrate, consider the following expression from the last line of the earlier CountNotEqual.cpp program:.
not1(bind1st(equal_to
The bind1st( ) adapter creates a unary function object of type binder1st, which simply stores an instance of equal_to
template
binder1st
bind1st(const Op& f, const T& val)
{
typedef typename Op::first_argument_type Arg1_t;
return binder1st
}
Note that the template parameter, Op, which represents the type of the binary function being adapted by bind1st( ), must have a nested type named first_argument_type. (Note also the use of typename to inform the compiler that it is a member
// Inside the implementation for binder1st
typename Op::result_type
operator()(const typename Op::second_argument_type& x)
const;
Function objects whose classes provide these type names are called