1061

I keep hearing a lot about functors in C++. Can someone give me an overview as to what they are and in what cases they would be useful?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
Konrad
  • 39,751
  • 32
  • 78
  • 114
  • 4
    This subject has been covered in response to this question: http://stackoverflow.com/questions/317450/why-override-operator#317528 – Luc Touraille Dec 10 '08 at 18:00
  • 2
    It is used to create a closure in C++. – copper.hat Jun 30 '19 at 04:13
  • 5
    Looking at answers below, if someone is wondering what does `operator()(...)` mean: it is overloading the the _"function call"_ operator. It is simply operator overloading for the `()` operator. Don't mistake `operator()` with calling a function called `operator`, but see it as the usual operator overloading syntax. – zardosht May 26 '20 at 13:22
  • Very closely related: [Why override `operator()`?](https://stackoverflow.com/a/317528/4561887) – Gabriel Staples Mar 13 '23 at 06:19

14 Answers14

1207

A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:

// this is a functor
struct add_x {
  add_x(int val) : x(val) {}  // Constructor
  int operator()(int y) const { return x + y; }

private:
  int x;
};

// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); 
assert(out[i] == in[i] + 1); // for all i

There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.

As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform should call. It should call add_x::operator(). That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.

If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
jalf
  • 243,077
  • 51
  • 345
  • 550
  • 44
    Can you explain this line, please std::transform(in.begin(), in.end(), out.begin(), add_x(1)); why you write there add_x, not the add42? – Alecs Sep 12 '11 at 14:48
  • 130
    @Alecs Both would have worked (but the effect would have been different). If I'd used `add42`, I would have used the functor I created earlier, and added 42 to each value. With `add_x(1)` I create a new instance of the functor, one which only adds 1 to each value. It is simply to show that often, you instantiate the functor "on the fly", when you need it, rather than creating it first, and keeping it around before you actually use it for anything. – jalf Sep 12 '11 at 15:12
  • 1
    Can the functors have other member functions as well? – zar Feb 08 '14 at 05:43
  • 8
    @zadane of course. They just have to have the `operator()`, because that is what the caller uses to invoke it. What *else* the functor has of member functions, constructors, operators and member variables is completely up to you. – jalf Feb 09 '14 at 12:37
  • `std::transform(in.begin(), in.end(), out.begin(), [](int &i){ i+=1;});` – caub Feb 15 '14 at 22:34
  • 3
    @crl Shouldn't that be `std::transform(in.begin(), in.end(), out.begin(), [](int i) { return i + 1; });`? – Mateen Ulhaq Sep 05 '15 at 12:58
  • 1
    "unlike regular functions, they can contain state" <- umm, regular functions can have static variables, so - they can contain state, albeit the semantics are a bit dodgy. – einpoklum Jan 24 '16 at 21:20
  • @jalf `class which defines the operator()` function isn't class but it still functor. – rikimaru2013 Feb 24 '16 at 11:08
  • 5
    @rikimaru2013 In the parlance of functional programming, you're correct, a function is also a functor, but in the parlance of C++, the functor is specifically a class used as a function. The terminology was a bit abused early on, but the division is useful distinction and so persists today. If you start referring to functions as "functors" in a C++ context then you'll just confuse the conversation. – srm Mar 28 '16 at 22:09
  • 7
    Is it a class or an instance of the class? In most sources, `add42` would be called a functor, not `add_x` (which is the class of the functor or just the functor class). I find that terminology consistent because functors are also called *function objects*, not function classes. Can you clarify this point? – Sergei Tachenov Jun 13 '16 at 14:41
  • so this is like in javascript when you have `function makeadd(bynumber){ return function(x){ return x + bynumber; }}` – Omu Nov 25 '16 at 20:45
  • It puzzled me for quite a while that you named `std::transform` a function. It isn't, it's a template which looks like a function in your code thanks to template parameter deduction. – Euri Pinhollow Jan 16 '17 at 12:50
  • 1
    I love when people not only explain something but also give the motivation for using it. Thank you. – JoeManiaci Apr 04 '17 at 17:49
  • 1
    @einpoklum functions can contain only one state unless you also pass the state (state itself or some value identifying state) as argument somehow. – Euri Pinhollow Nov 27 '17 at 17:55
  • The answer is good but it lacks some important data which is obvious to experienced programmers but not so much to newbies: 1) only function templates have advantage of making it obvious for compiler what function was used. 2) If function accepts `std::function` then the advantage of inlining is lost. --------- When I first read this answer years ago it left me in buggy state because of argument deduction which hidden the fact that you cannot pass any object to non-template function. – Euri Pinhollow Nov 27 '17 at 18:03
  • @EuriPinhollow when you pass arguments, e.g. `std::transform(in.begin(), in.end(), out.begin(), add_x(1))`, you have a function call. You are right that `std::transform` *on it's own* is not a function. – Caleth Mar 06 '18 at 15:40
  • 1
    One more comment: it is still possible to inline function even if it is passed as `function` object value. BUT: compilers are able to inline calls even if function is passed by pointer, you do not need to have a template for that. It's just that with function template you cannot pass function defined at run time. – Euri Pinhollow Mar 09 '18 at 21:28
  • This is true. But with the new C++ 11 `lambdas` functors are pretty much dead. Now you may not need to create a whole class to have the function, instead have the function inlined in the method call. Lambdas are equally powerful in terms of both usage and performance. – Sisir Feb 12 '19 at 14:37
  • 1
    @Sisir when you only have one `operator()`, sure. If you have a bunch of different `operator()`s sharing state then multiple lambdas are harder to get right than an explicit closure class – Caleth Jul 02 '19 at 10:10
  • What does `std::transform(in.begin(), in.end(), out.begin(), add_x(1)); ` do at the first iteration, please? – Franky Apr 10 '20 at 19:56
  • I'm specifically curious about the name *functor*, is this have anything to do with functors in cats theory? I've just heard this word from some friends, and I know nothing of it, nor am I interested in that direction -- just curious. – Ray Eldath Jul 26 '20 at 16:51
131

Little addition. You can use boost::function, to create functors from functions and methods, like this:

class Foo
{
public:
    void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"

and you can use boost::bind to add state to this functor

boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"

and most useful, with boost::bind and boost::function you can create functor from class method, actually this is a delegate:

class SomeClass
{
    std::string state_;
public:
    SomeClass(const char* s) : state_(s) {}

    void method( std::string param )
    {
        std::cout << state_ << param << std::endl;
    }
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"

You can create list or vector of functors

std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
        events.begin(), events.end(), 
        boost::bind( boost::apply<void>(), _1, e));

There is one problem with all this stuff, compiler error messages is not human readable :)

Ziezi
  • 6,375
  • 3
  • 39
  • 49
Evgeny Lazin
  • 9,193
  • 6
  • 47
  • 83
  • 4
    Shouldn't `operator ()` be public in your first example since classes default to private? – NathanOliver Jun 16 '15 at 13:43
  • 9
    maybe at some point this answer deserves an update, since now lambdas are the easiest way to get a functor from whatever – 463035818_is_not_an_ai Jan 30 '19 at 18:29
  • 1
    int C++11 there are [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) and [`std::bind`](https://en.cppreference.com/w/cpp/utility/functional/bind) – phuclv Oct 25 '20 at 09:26
129

A Functor is a object which acts like a function. Basically, a class which defines operator().

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

The real advantage is that a functor can hold state.

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}
Ziezi
  • 6,375
  • 3
  • 39
  • 49
James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 13
    Just need to add that they can be used just like a function pointer. – Martin York Dec 10 '08 at 18:04
  • 11
    @LokiAstari - For those that are new to the concept, that could be a bit misleading. Functors can be "used like", but not always "in place of" function pointers. For example, a function that takes a function pointer cannot take a functor in its place even if the functor has the same arguments and return value as the function pointer. But by and large when designing, functors are the preferred and theoretically "more modern" way to go. – MasonWinsauer Mar 12 '14 at 21:49
  • Why does the second one return `int` when it should return `bool`? This is C++, not C. When this answer was written, did `bool` not exist? – Nic May 08 '16 at 17:40
  • @QPaysTaxes A typo I guess. I probably copy'n'pasted the code from the first example and forgot to change it. I've fixed it now. – James Curran May 10 '16 at 18:09
  • Oh, that makes sense. Thanks for bearing with my pedantry :) – Nic May 10 '16 at 18:15
  • What's the advantage using over bool Is5(int n) {return 5==n;} – StarDust Sep 29 '17 at 20:16
  • 1
    @Riasat If Matcher is in a library, defining Is5() is quite simple. ANd you can create Is7(), Is32() etc. Further, that's just an example. THe functor could be much more complicate. – James Curran Sep 30 '17 at 02:57
68

Name "functor" has been traditionaly used in category theory long before C++ appeared on the scene. This has nothing to do with C++ concept of functor. It's better to use name function object instead of what we call "functor" in C++. This is how other programming languages call similar constructs.

Used instead of plain function:

Features:

  • Function object may have state
  • Function object fits into OOP (it behaves like every other object).

Cons:

  • Brings more complexity to the program.

Used instead of function pointer:

Features:

  • Function object often may be inlined

Cons:

  • Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)

Used instead of virtual function:

Features:

  • Function object (non-virtual) doesn't require vtable and runtime dispatching, thus it is more efficient in most cases

Cons:

  • Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
mip
  • 8,355
  • 6
  • 53
  • 72
  • 2
    Can you explain these use case in real example? how can we use functors as polymorphism adn funtion pointer? – Milad Khajavi Feb 21 '13 at 17:40
  • 1
    What actually does mean that a functor holds state? – erogol Apr 15 '13 at 12:05
  • thanks for pointing out that one needs a base class to have some kind of polymorphism. I just have the problem that I have to use a functor in the same place as a simple function pointer and the only way I found was to write a functor base class (as I cannot use C++11 stuff). Wasnt sure if this overhead makes sense until i read your answer. – 463035818_is_not_an_ai Jan 09 '15 at 12:36
  • 1
    @Erogol A functor is an object which happens to support the syntax `foo(arguments)`. Therefore, it can contain variables; for example, if you had an `update_password(string)` function, you might want to keep track of how often that had happened; with a functor, that can be a `private long time` representing the timestamp it last happened. With a function pointer or plain function, you'd need to use a variable outside of its namespace, which is only directly related by documentation and usage, rather than by definition.l – Nic May 09 '16 at 17:10
  • 6
    ⁺¹ for mentioning that the name have been made up for no reason. I've just been searching for what's the relation between mathematical *(or functional if you want)* functor and the one from C++. – Hi-Angel Oct 15 '17 at 18:25
  • Thanks for elaborating the misleading use of the word functor. – copper.hat Feb 10 '19 at 07:55
46

For the newbies like me among us: after a little research I figured out what the code jalf posted did.

A functor is a class or struct object which can be "called" like a function. This is made possible by overloading the () operator. The () operator (not sure what its called) can take any number of arguments. Other operators only take two i.e. the + operator can only take two values (one on each side of the operator) and return whatever value you have overloaded it for. You can fit any number of arguments inside a () operator which is what gives it its flexibility.

To create a functor first you create your class. Then you create a constructor to the class with a parameter of your choice of type and name. This is followed in the same statement by an initializer list (which uses a single colon operator, something I was also new to) which constructs the class member objects with the previously declared parameter to the constructor. Then the () operator is overloaded. Finally you declare the private objects of the class or struct you have created.

My code (I found jalf's variable names confusing)

class myFunctor
{ 
    public:
        /* myFunctor is the constructor. parameterVar is the parameter passed to
           the constructor. : is the initializer list operator. myObject is the
           private member object of the myFunctor class. parameterVar is passed
           to the () operator which takes it and adds it to myObject in the
           overloaded () operator function. */
        myFunctor (int parameterVar) : myObject( parameterVar ) {}

        /* the "operator" word is a keyword which indicates this function is an 
           overloaded operator function. The () following this just tells the
           compiler that () is the operator being overloaded. Following that is
           the parameter for the overloaded operator. This parameter is actually
           the argument "parameterVar" passed by the constructor we just wrote.
           The last part of this statement is the overloaded operators body
           which adds the parameter passed to the member object. */
        int operator() (int myArgument) { return myObject + myArgument; }

    private: 
        int myObject; //Our private member object.
}; 

If any of this is inaccurate or just plain wrong feel free to correct me!

Ziezi
  • 6,375
  • 3
  • 39
  • 49
Johanne Irish
  • 1,033
  • 2
  • 10
  • 17
46

Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.

Functors are commonly used in STL algorithms. They are useful because they can hold state before and between function calls, like a closure in functional languages. For example, you could define a MultiplyBy functor that multiplies its argument by a specified amount:

class MultiplyBy {
private:
    int factor;

public:
    MultiplyBy(int x) : factor(x) {
    }

    int operator () (int other) const {
        return factor * other;
    }
};

Then you could pass a MultiplyBy object to an algorithm like std::transform:

int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}

Another advantage of a functor over a pointer to a function is that the call can be inlined in more cases. If you passed a function pointer to transform, unless that call got inlined and the compiler knows that you always pass the same function to it, it can't inline the call through the pointer.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Matthew Crumley
  • 101,441
  • 24
  • 103
  • 129
  • 1
    I was looking exactly for this example because I have just seen it in a C++ course and I wasn't understanding it. Usually, we define an object of a class, which implements operator(), and pass it as an argument, a functor, to a function such as `transform`. However, in this case we are just constructing the object in the same call. Is that the only difference? That the functor goes out of scope and is destroyed once `transform` finishes? Thanks! – rturrado Feb 16 '21 at 14:04
26

A functor is a higher-order function that applies a function to the parametrized(ie templated) types. It is a generalization of the map higher-order function. For example, we could define a functor for std::vector like this:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
    std::vector<U> result;
    std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
    return result;
}

This function takes a std::vector<T> and returns std::vector<U> when given a function F that takes a T and returns a U. A functor doesn't have to be defined over container types, it can be defined for any templated type as well, including std::shared_ptr:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
    if (p == nullptr) return nullptr;
    else return std::shared_ptr<U>(new U(f(*p)));
}

Heres a simple example that converts the type to a double:

double to_double(int x)
{
    return x;
}

std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);

std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);

There are two laws that functors should follow. The first is the identity law, which states that if the functor is given an identity function, it should be the same as applying the identity function to the type, that is fmap(identity, x) should be the same as identity(x):

struct identity_f
{
    template<class T>
    T operator()(T x) const
    {
        return x;
    }
};
identity_f identity = {};

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);

The next law is the composition law, which states that if the functor is given a composition of two functions, it should be the same as applying the functor for the first function and then again for the second function. So, fmap(std::bind(f, std::bind(g, _1)), x) should be the same as fmap(f, fmap(g, x)):

double to_double(int x)
{
    return x;
}

struct foo
{
    double x;
};

foo to_foo(double x)
{
    foo r;
    r.x = x;
    return r;
}

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));
Paul Fultz II
  • 17,682
  • 13
  • 62
  • 59
  • 2
    Article arguing that functor should correctly be used for this meaning (see also https://en.wikipedia.org/wiki/Functor), and that using it for function objects is just sloppy: http://jackieokay.com/2017/01/26/functors.html It may be too late for that though, given the number of answers here that only consider the function object meaning. – armb Feb 12 '17 at 13:33
  • 4
    This answer should be the one with >700 Upvotes. As someone how knows Haskell better than C++, the C++ lingua puzzled me all the times. – mschmidt Dec 26 '17 at 21:34
  • 1
    Category theory and C++? Is this Bartosz Milewski's secret SO account? – Mateen Ulhaq Aug 07 '18 at 23:35
  • 1
    It might be helpful to summarize the functor laws in standard notation: `fmap(id, x) = id(x)` and `fmap(f ◦ g, x) = fmap(f, fmap(g, x))`. – Mateen Ulhaq Aug 07 '18 at 23:40
  • @mschmidt whilst functor also means this, C++ overloads the name to mean the same as "function object" – Caleth Jul 02 '19 at 10:16
  • 1
    There is no mention of functor in the C++ standard. cppreference.com provides no definition of functor while it does provide a definition of [FunctionObject](https://en.cppreference.com/w/cpp/named_req/FunctionObject) with no mention of functor at all. – Paul Fultz II Jul 02 '19 at 16:46
  • C++ and math terminology diverge in a lot of areas. This is neither undesirable nor wrong. E.g. "vector". Math concepts like "array", "sequence", "matrix" or "vector" have no equivalent in programming, because programming requires a concrete data type, which math is completely unconcerned with. In math you might talk about a sequence of numbers, but in programming this is meaningless. Are you talking about a list? a vector? a deque? The fact that some of these terms duplicate mathematical ones is fine. Even "function" does not have the mathematical meaning, which is why function object fails. – rnpl Sep 05 '19 at 17:30
9

Here's an actual situation where I was forced to use a Functor to solve my problem:

I have a set of functions (say, 20 of them), and they are all identical, except each calls a different specific function in 3 specific spots.

This is incredible waste, and code duplication. Normally I would just pass in a function pointer, and just call that in the 3 spots. (So the code only needs to appear once, instead of twenty times.)

But then I realized, in each case, the specific function required a completely different parameter profile! Sometimes 2 parameters, sometimes 5 parameters, etc.

Another solution would be to have a base class, where the specific function is an overridden method in a derived class. But do I really want to build all of this INHERITANCE, just so I can pass a function pointer????

SOLUTION: So what I did was, I made a wrapper class (a "Functor") which is able to call any of the functions I needed called. I set it up in advance (with its parameters, etc) and then I pass it in instead of a function pointer. Now the called code can trigger the Functor, without knowing what is happening on the inside. It can even call it multiple times (I needed it to call 3 times.)


That's it -- a practical example where a Functor turned out to be the obvious and easy solution, which allowed me to reduce code duplication from 20 functions to 1.

Fellow Traveler
  • 324
  • 4
  • 8
  • 3
    If your functor called different specific functions, and these other functions varied in the number of parameters they accept, does this mean your functor accepted a variable number of arguments for dispatching to these other functions? – johnbakers Feb 28 '14 at 06:09
  • 6
    can you please explain the above scenario by quoting some part of code , i am new to c++ want to understand this concept.. – sanjeev Sep 05 '17 at 10:13
4

Like has been repeated, functors are classes that can be treated as functions (overload operator ()).

They are most useful for situations in which you need to associate some data with repeated or delayed calls to a function.

For example, a linked-list of functors could be used to implement a basic low-overhead synchronous coroutine system, a task dispatcher, or interruptable file parsing. Examples:

/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
    std::string output;
    Functor(const std::string& out): output(out){}
    operator()() const
    {
        std::cout << output << " ";
    }
};

int main(int argc, char **argv)
{
    std::list<Functor> taskQueue;
    taskQueue.push_back(Functor("this"));
    taskQueue.push_back(Functor("is a"));
    taskQueue.push_back(Functor("very simple"));
    taskQueue.push_back(Functor("and poorly used"));
    taskQueue.push_back(Functor("task queue"));
    for(std::list<Functor>::iterator it = taskQueue.begin();
        it != taskQueue.end(); ++it)
    {
        *it();
    }
    return 0;
}

/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
    std::cout << "i = " << i << std::endl;
    std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
    std::cin >> should_increment;
    return 2;
}
void doSensitiveWork()
{
     ++i;
     should_increment = false;
}
class BaseCoroutine
{
public:
    BaseCoroutine(int stat): status(stat), waiting(false){}
    void operator()(){ status = perform(); }
    int getStatus() const { return status; }
protected:
    int status;
    bool waiting;
    virtual int perform() = 0;
    bool await_status(BaseCoroutine& other, int stat, int change)
    {
        if(!waiting)
        {
            waiting = true;
        }
        if(other.getStatus() == stat)
        {
            status = change;
            waiting = false;
        }
        return !waiting;
    }
}

class MyCoroutine1: public BaseCoroutine
{
public:
    MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
    BaseCoroutine& partner;
    virtual int perform()
    {
        if(getStatus() == 1)
            return doSomeWork();
        if(getStatus() == 2)
        {
            if(await_status(partner, 1))
                return 1;
            else if(i == 100)
                return 0;
            else
                return 2;
        }
    }
};

class MyCoroutine2: public BaseCoroutine
{
public:
    MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
    bool& work_signal;
    virtual int perform()
    {
        if(i == 100)
            return 0;
        if(work_signal)
        {
            doSensitiveWork();
            return 2;
        }
        return 1;
    }
};

int main()
{
     std::list<BaseCoroutine* > coroutineList;
     MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
     MyCoroutine1 *printer = new MyCoroutine1(incrementer);

     while(coroutineList.size())
     {
         for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
             it != coroutineList.end(); ++it)
         {
             *it();
             if(*it.getStatus() == 0)
             {
                 coroutineList.erase(it);
             }
         }
     }
     delete printer;
     delete incrementer;
     return 0;
}

Of course, these examples aren't that useful in themselves. They only show how functors can be useful, the functors themselves are very basic and inflexible and this makes them less useful than, for example, what boost provides.

nfries88
  • 374
  • 6
  • 7
3

Except for used in callback, C++ functors can also help to provide a Matlab liking access style to a matrix class. There is a example.

Yantao Xie
  • 12,300
  • 15
  • 49
  • 79
  • This (the matrix example) is plain use of `operator()` but not making use of function object properties. – foxesque Jul 04 '19 at 09:40
2

A big advantage of implementing functions as functors is that they can maintain and reuse state between calls. For example, many dynamic programming algorithms, like the Wagner-Fischer algorithm for calculating the Levenshtein distance between strings, work by filling in a large table of results. It's very inefficient to allocate this table every time the function is called, so implementing the function as a functor and making the table a member variable can greatly improve performance.

Below is an example of implementing the Wagner-Fischer algorithm as a functor. Notice how the table is allocated in the constructor, and then reused in operator(), with resizing as necessary.

#include <string>
#include <vector>
#include <algorithm>

template <typename T>
T min3(const T& a, const T& b, const T& c)
{
   return std::min(std::min(a, b), c);
}

class levenshtein_distance 
{
    mutable std::vector<std::vector<unsigned int> > matrix_;

public:
    explicit levenshtein_distance(size_t initial_size = 8)
        : matrix_(initial_size, std::vector<unsigned int>(initial_size))
    {
    }

    unsigned int operator()(const std::string& s, const std::string& t) const
    {
        const size_t m = s.size();
        const size_t n = t.size();
        // The distance between a string and the empty string is the string's length
        if (m == 0) {
            return n;
        }
        if (n == 0) {
            return m;
        }
        // Size the matrix as necessary
        if (matrix_.size() < m + 1) {
            matrix_.resize(m + 1, matrix_[0]);
        }
        if (matrix_[0].size() < n + 1) {
            for (auto& mat : matrix_) {
                mat.resize(n + 1);
            }
        }
        // The top row and left column are prefixes that can be reached by
        // insertions and deletions alone
        unsigned int i, j;
        for (i = 1;  i <= m; ++i) {
            matrix_[i][0] = i;
        }
        for (j = 1; j <= n; ++j) {
            matrix_[0][j] = j;
        }
        // Fill in the rest of the matrix
        for (j = 1; j <= n; ++j) {
            for (i = 1; i <= m; ++i) {
                unsigned int substitution_cost = s[i - 1] == t[j - 1] ? 0 : 1;
                matrix_[i][j] =
                    min3(matrix_[i - 1][j] + 1,                 // Deletion
                    matrix_[i][j - 1] + 1,                      // Insertion
                    matrix_[i - 1][j - 1] + substitution_cost); // Substitution
            }
        }
        return matrix_[m][n];
    }
};
2

Functors are used in gtkmm to connect some GUI button to an actual C++ function or method.


If you use the pthread library to make your app multithreaded, Functors can help you.
To start a thread, one of the arguments of the pthread_create(..) is the function pointer to be executed on his own thread.
But there's one inconvenience. This pointer can't be a pointer to a method, unless it's a static method, or unless you specify it's class, like class::method. And another thing, the interface of your method can only be:

void* method(void* something)

So you can't run (in a simple obvious way), methods from your class in a thread without doing something extra.

A very good way of dealing with threads in C++, is creating your own Thread class. If you wanted to run methods from MyClass class, what I did was, transform those methods into Functor derived classes.

Also, the Thread class has this method: static void* startThread(void* arg)
A pointer to this method will be used as an argument to call pthread_create(..). And what startThread(..) should receive in arg is a void* casted reference to an instance in heap of any Functor derived class, which will be casted back to Functor* when executed, and then called it's run() method.

Guido Tarsia
  • 1,962
  • 4
  • 27
  • 45
1

To add on, I have used function objects to fit an existing legacy method to the command pattern; (only place where the beauty of OO paradigm true OCP I felt ); Also adding here the related function adapter pattern.

Suppose your method has the signature:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

We will see how we can fit it for the Command pattern - for this, first, you have to write a member function adapter so that it can be called as a function object.

Note - this is ugly, and may be you can use the Boost bind helpers etc., but if you can't or don't want to, this is one way.

// a template class for converting a member function of the type int        function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
  public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
    :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
    return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};

Also, we need a helper method mem_fun3 for the above class to aid in calling.

template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm)          (_arg1,_arg2,_arg3) )
{
  return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));
}

Now, in order to bind the parameters, we have to write a binder function. So, here it goes:

template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
    :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}

 //and this is the function object 
 void operator()() const
 {
        m_fn(m_ptr,m1,m2,m3);//that calls the operator
    }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

And, a helper function to use the binder3 class - bind3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

Now, we have to use this with the Command class; use the following typedef:

typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
    method3 = p_method;
}

Here is how you call it:

F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
      &CTask::ThreeParameterTask), task1,2122,23 );

Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);.

The full context of this pattern at the following link

phuclv
  • 37,963
  • 15
  • 156
  • 475
Alex Punnen
  • 5,287
  • 3
  • 59
  • 71
1

Functor can also be used to simulate defining a local function within a function. Refer to the question and another.

But a local functor can not access outside auto variables. The lambda (C++11) function is a better solution.

Community
  • 1
  • 1
Yantao Xie
  • 12,300
  • 15
  • 49
  • 79