| I l@ve RuBoard |
|
4.9 Implementing a Function ObjectIn Section 3.6, we looked at the predefined function objects of the standard library. In this section, we look at how to implement our own function objects. A function object is a class that provides an overloaded instance of the function call operator. When the compiler encounters what appears to be a function call, such as lt( ival ); lt can be the name of a function, a pointer to function, or an object of a class that has provided an instance of the function call operator. If lt is a class object, the compiler internally transforms the statement as follows: lt.operator()( ival ); // internal transformation The function call operator can take any number of parameters: none, one, two, and so on. It is used, for example, to support multidimensional subscripting of a Matrix class because the actual subscript operator is limited to accepting one parameter. Let's implement an overloaded instance of the call operator to test whether a value passed to it is less than some other value. We'll call the class LessThan. Each object must be initialized with a value against which to compare. In addition, we support read and write access of that value. Here's our implementation:
class LessThan {
public:
LessThan( int val ) : _val( val ){}
int comp_val() const { return _val; }
void comp_val( int nval ){ _val = nval; }
bool operator()( int value ) const;
private:
int _val;
};
The implementation of the function call operator looks like this:
inline bool LessThan::
operator()( int value ) const { return value < _val; }
We can explicitly define a LessThan class object in the same way as any other class object: LessThan lt10( 10 ); We invoke the overloaded call operator function by applying the call operator (()) to the class object. For example,
int count_less_than( const vector<int> &vec, int comp )
{
LessThan lt( comp );
int count = 0;
for ( int ix = 0; ix < vec.size(); ++ix )
if ( lt( vec[ ix ] ))
++count;
return count;
}
More typically, we pass a function object as an argument to a generic algorithm:
void print_less_than( const vector<int> &vec,
int comp, ostream &os = cout )
{
LessThan lt( comp );
vector<int>::const_iterator iter = vec.begin();
vector<int>::const_iterator it_end = vec.end();
os << "elements less than " << lt.comp_val() << endl;
while (( iter = find_if( iter, it_end, lt )) != it_end )
{
os << *iter << ' ';
++iter;
}
}
Here's a small program to exercise these two functions:
int main()
{
int ia[16] = { 17, 12, 44, 9, 18, 45, 6, 14,
23, 67, 9, 0, 27, 55, 8, 16 };
vector<int> vec( ia, ia+16 );
int comp_val = 20;
cout << "Number of elements less than "
<< comp_val << " are "
<< count_less_than( vec, comp_val ) << endl;
print_less_than( vec, comp_val );
}
When compiled and executed, the program generates the following output: Number of elements less than 20 are 10 elements less than 20 17 12 9 18 6 14 9 0 8 16 Appendix B provides additional examples of function object definitions. |
| I l@ve RuBoard |
|