- What Do We Mean by Generalization?
- What Are Function Objects and Predicates?
- User-Defined Function Objects
- Conclusion
What Are Function Objects and Predicates?
Objects that have the operator() defined can be used as functions, and in most cases as replacements for functions. When the return value for an object’s definition of operator() is a bool (true or false), that object can be used as a predicate. That is, a predicate is a function that returns true or false.
In C++, a predicate is a special kind of function object. Function objects have a distinct advantage over traditional functions. Because function objects are first and foremost objects, they have all the advantages of objects—class hierarchies, methods, state variables, operators, and so on. They can be passed as objects and held in containers. The state variables of a function object can be accessed before and after they’re used with any container or algorithm.
C++ has a number of built-in function objects and predicates. Table 2 lists the most commonly used function objects and predicates.
Table 2 Most Commonly Used Function Objects and Predicates in the C++ Standard Library
Function Object/Predicate |
Effect |
negate<type>() |
- param |
plus <type>() |
param1 + param2 |
minus <type>() |
param1 - param2 |
multiplies<type>() |
param1 * param2 |
divides<type>() |
param1 / param2 |
modulus<type>() |
param1 % param2 |
equal_to<type>() |
param1 == param2 |
not_equal_to<type>() |
param1 != param2 |
less<type>() |
param1 < param2 |
greater<type>() |
param1 > param2 |
less_equal<type>() |
param1 <= param2 |
greater_equal<type>() |
param1 >= param2 |
logical_not<type>() |
! param |
logical_and<type>() |
param1 && param2 |
logical_or<type>() |
param1 || param2 |
Many of the standard algorithms accept function objects as parameters. The built-in function objects work easily with these algorithms. The example in Listing 2 uses the multiplies() and less() function objects.
Listing 2 Using the multiplies() and less() function objects.
using namespace std; #include <iostream> #include <vector> #include <algorithm> #include <iterator> int main(int argc,char *argv[]) { ... vector<float> Num; Num.push_back(4.7); Num.push_back(5.7); Num.push_back(6.7); transform(Num.begin(),Num.end(),Num.begin(),bind2nd(multiplies<float>(),3)); copy(Num.begin(),Num.end(),ostream_iterator<float>(cout,"\n")); cout << count_if(Num.begin(),Num.end(),bind2nd(less<float>(),15)); ... }
The multiplies() function object multiplies two values and returns the result. The less() function object takes two values and returns true if the second value is less than the first. multiplies() is a function object and less() is an example of a predicate. Notice in Listing 2 that multiplies and less are called as arguments to the bind2nd() function adapter. This is necessary because both multiplies() and less() take two arguments. In both cases, the first argument will be supplied by a value from the container. We use the bind2nd() function adapter to supply the second value. This is a standard operation when using function objects with the container classes. Several of the built-in function objects require two values. Whenever they’re used with the algorithms and a container, a function adapter is needed to bind the second value. The bind2nd() function adapter binds the second argument and the bind1st() function adapter binds the first argument.