Introduction
This article talks about Function Object and it's uses over Function Pointers
Background
A Function Object, is an Object of a class that defines an operator () and can be called as a function. When a function object is used as a function, the function call operator() is invoked and does the similar way as by calling a function.
Remember that the overloaded operator () can have a varying number of arguments, and any return value. These function objects are frequently used in numerical methods implementation.
It's uses :
1. More resilient to design changes as objects can be modified without affecting it's external interface.
2. Function objects are faster than functions as many a times an invocation of a function object, can be expanded in-line and thus eliminating the overhead of a function call. Whereas it is nearly impossible to inline a non-static function that is called through functions poiners.
3. It can emobody a generic alogorithm by means of a member template.
4. It is possible to perform very sophisticated operations without actually writing a new function object, simply by combining predefined function objects, like the way currently it is done in STL.
5. Function objects are more powefull than functions, since they can have data members and there carry around information or internal states.
An example to illustrate the last point is below:
Code: Cpp
#include<iostream.h>
class iotaGen
{
public:
iotaGen (int start = 0) : current(start) { }
int operator() () { return current++; }
private:
int current;
};
void initializeArray(int (*arr), iotaGen &gen)
{
int i;
i=0;
while(20 > i)
{
arr[i] = gen();
cout<<"arr["<<i<<"]="<<arr[i]<<"\n";
++i;
}
}
int main()
{
iotaGen a(1);
int arr[20];
cout<<"Initializing array using Function Object...\n\n";
initializeArray(arr, a);
return (0);
}
Output:
Initializing array using Function Object...
arr[0]=1
arr[1]=2
arr[2]=3
arr[3]=4
arr[4]=5
arr[5]=6
arr[6]=7
arr[7]=8
arr[8]=9
arr[9]=10
arr[10]=11
arr[11]=12
arr[12]=13
arr[13]=14
arr[14]=15
arr[15]=16
arr[16]=17
arr[17]=18
arr[18]=19
arr[19]=20
This is an example where, iotaGen object maintains a current value, which can be set by the constructor, or defaults to zero. Each time the function-call operator() is invoked, the current value is returned, and also incremented.
This is also used in the creation of a generator, to be used with the generic algorithm std::generate(). A generator is simply a function object that takes no arguments and returns a new value each time it is invoked.
Using iotaGen object, the following call on the standard library function generate() will initialize a vector of 20 elements with the values 1 through 20:
Code: Cpp
vector<int> aVec(20);
generate (aVec.begin(), aVec.end(), iotaGen(1));
Here is another example where Function Object acts as a Generic Compare Function. Here in the main function - cf is a object of CompareFunc, that is passed to a function called findMatch and so works as a callback function.
The code
Code: Cpp
#include <iostream.h>
template <class Type>
class CompareFunc
{
public:
bool operator()(const Type &x, const Type &y)
{
return (x==y);
}
};
void findMatch(const char* str1, const char* str2, CompareFunc<const char*> &cf)
{
if( cf(str1, str2))
{
cout<<str1<<" & "<<str2<<" -> matches\n";
}
else
{
cout<<str1<<" & "<<str2<<" -> does not match\n";
}
}
int main()
{
CompareFunc<const char*> cf;
//calling function findMatch by CompareFunc object "cf"
findMatch("Hello","World",cf);
findMatch("Hello","Hello",cf);
return(0);
}
output:
./a.out
Hello & World -> does not match
Hello & Hello -> matches

