tags:

views:

8994

answers:

7

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?

A: 

See this article. Essentially, a functor is a wrapper around a function pointer. They are functions with a state.

Excerpt: "Functors are functions with a state. In C++ you can realize them as a class with one or more private members to store the state and with an overloaded operator () to execute the function. Functors can encapsulate C and C++ function pointers employing the concepts templates and polymorphism. You can build up a list of pointers to member functions of arbitrary classes and call them all through the same interface without bothering about their class or the need of a pointer to an instance. All the functions just have got to have the same return-type and calling parameters. Sometimes functors are also known as closures. You can also use functors to implement callbacks."

j0rd4n
+11  A: 

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) {}
     int operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}
James Curran
Just need to add that they can be used just like a function pointer.
Martin York
+37  A: 

A functor is pretty much just a class which defines the operator(). That makes it "look like" a function:

struct add_x {
  add_x(int x) : x(x) {}
  int operator()(int y) { return x + y; }

private:
  int x;
};

// Now you can use it like this:
add_x add42(42); // create a functor
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;
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); // 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
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, 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. 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 more efficient. In the above example, the compiler knows exactly which function transform calls. It calls add_x::operator(). That means it can inline that function call. 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.

jalf
+6  A: 

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 an MultiplyBy functor that multiplies it's 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 Multiply 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 to 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.

Matthew Crumley
+1 for mentioning 'inline'; a key difference.
Richard Corden
+12  A: 

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

class Foo
{
    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 :)

Lazin
Vector of functors -- that's worth two upvotes!
redmoskito
A: 

The Command Pattern suggests many problem/solution domains in which functors may be useful.

leander
+1  A: 

Used instead of plain function:

Pros:

  • Functor may have state
  • Functor fits into OOP

Cons:

  • There is more typing, a bit longer compilation time etc.


Used instead of function pointer:

Pros:

  • Functor often may be inlined

Cons:

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


Used instead of polymorphism:

Pros:

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

Cons:

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