How To Create Functors and Function Objects
Written by Mike James   
Monday, 17 June 2024
Article Index
How To Create Functors and Function Objects
Creating a Functor
Passing function objects

Passing function objects

As a function object is just a standard object you can pass it as a parameter in another method. For example:

class MyClass
{
public:
void MyMethod(MyFunctor F)
{
int result=F(1);
}
};

Notice that MyMethod accepts a parameter of type MyFunctor and when supplied simply calls it as a function. For example:

MyFunctor MyFunction(2);
MyClass MyObject;
MyObject.MyMethod(MyFunction);

Comparing this to using a function pointer you can see that not only is it simpler, it fits in much better with the object-oriented idea. However, it has to be admitted that you can't do the same fancy tricks that you can achieve with a pointer - for example changing the function the pointer references at run time. This said function objects are heavily used in the STL to pass functions - often predicates - into methods.

The complete program is:

class MyFunctor
{
private:
    int inc;
    int count;
public:
    MyFunctor(int value)
    {
        count = 0;
        inc = value;
    };
    int operator()(int i)
    {
        count++;
        return i + inc;
    }
};
class MyClass
{
public:
    int MyMethod(MyFunctor F)
    {
        int result = F(1);
        return result;
    }
};
int main()
{
    MyFunctor MyFunction(2);
    MyClass MyObject;
    int result=MyObject.MyMethod(MyFunction);
    std::cout << result;
}

An example of closure

Returning for a moment to the idea that function object allow C++ programmers to implement closure we can see how this works with a simple example. One of the common uses of closure is to allow a callback function to access variables that are defined within its original context. For example suppose you have to supply a callback function to an object that searches an index for a target. You could implement a cut off value that aborted the search when the number of hits reaches a limit. If C++ implemented closure you could do this as follows.

First define the callback as a function object:

int operator () (Results Rs)
{
if(Rs.Hits>HitLimit) abort;
}

where it is assumed that the callback accepts an object of type Results that the search object uses to communicate the progress of the search. Notice that the signature of the callback function is predefined by the object using the callback - you can't change it.

This is all fairly simply except for where the HitLimit variable comes from. Notice that you can't include HitLimit as a parameter in the callback function because it has to fit the specification supplied for the callback. If C++ supported closure directly we could just create HitLimit as a local variable in the same scope as the function - closure would then make the variable available within the function even if the local context had been destroyed. That is, if C++ supported closure you could just write:

int HitLimit=5;
MyFunctor MyFunction(10);
. . .
MyObject.MyMethod(MyFunction);

Yes this would be enough to make HitLimit accessible within MyFunction if closure was in effect.

However we all know that C++ doesn't implement closure so what you have to do is simply add a suitable property to the function object or use the constructor to initialize a private variable:

class MyFunctor
{
private:
int HitLimit;
public:
MyFunctor(int value)
{
HitLimit=value;
};
int operator () (Results Rs)
{
if(Rs.Hits > this->HitLimit) abort;
}
};

Then you can use the callback as:

MyFunctor MyFunction(10);
MyObject.MyMethod(MyFunction);

Using a property has the advantage the it makes clear what is being set e.g.

MyFunction.HitLimit=10;
MyObject.MyMethod(MyFunction);

There are lots of very clever and sophisticated uses of function objects. The sorts of things you need to keep in mind are that because a function object is just an object it can take part in inheritance, polymorphism and you can use templates to create generic functors.

However as with most of C++ just because it is possible doesn't means it is a good idea.

Try and keep things simple.

operators

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


OpenAI Library For .NET Exits Beta
19/11/2024

A few months ago the OpenAI .NET library was released as a beta. It has now reached version 2.0.0 and the time has come to leave beta and, with a few amendments enter production readiness.



IBM Opensources AI Agents For GitHub Issues
14/11/2024

IBM is launching a new set of AI software engineering agents designed to autonomously resolve GitHub issues. The agents are being made available in an open-source licensing model.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Monday, 17 June 2024 )