views:

277

answers:

6

I see function objects used often together with STL algorithms. Did function objects came about because of these algorithms? When do you use a function object in C++? What is its benefits?

+2  A: 

Function objects were designed to allow a strong layer of abstraction over STL, and in that regard they are great.

However, I prefer to use boost::bind and bind a function to the STL algorithms instead -- usually (although not in cases where the object has a state) that seems a more elegant solution.

std::for_each( callback.begin(), callback.end(), 
    boost::bind(&Callback::call(),_1) 
);

Also, another upcoming alternative are lambda's in C++0x (example shamelessly stolen from Wikipedia):

std::vector<int> someList;
int total = 0;
std::for_each(someList.begin(), someList.end(), [&total](int x) {
  total += x;
});
std::cout << total;

Notice that due to closures, they do not have the restriction of bind about not having a state.

Kornel Kisielewicz
+5  A: 

Function objects (functors) are typically used instead of function pointers. Function pointers have the problem that the compiler typically passes them as raw pointers, which makes it hard for the compiler to inline the code later. And they're easier to give parameters.

jdv
+1 - For the mentioning inlining
RC
So I guess functors are used more for their efficiency...
jasonline
@jasonline: That's not the only advantage, but in many cases it is the primary advantage.
jdv
A: 

I can't say why they came about - possibly simply because they could!

When do you use a functor? Consider that a functor is just moving the code you'd normally put in a loop into the operator() of a class, they're not that much different from just calling a function in a while loop... except, by using them you allow the compiler to inline the code and you can also pass a pre-constructed object instead, that you've constructed with some state. That latter point makes them very powerful.

Compare the sort algorithm with the CRTs qsort call. They do the same thing, only do it quite differently.

gbjbaanb
+5  A: 

As said jdv, functors are used instead of function pointers, that are harder to optimize and inline for the compiler; moreover, a fundamental advantage of functors is that they can easily preserve a state between calls to them1, so they can work differently depending on the other times they have been called, keep track somehow of the parameters they have used, ...

For example, if you want to sum all the elements in two containers of ints you may do something like this:

struct
{
    int sum;
    void operator()(int element) { sum+=element; }
} functor;
functor.sum=0;
std::for_each(your_first_container.begin(), your_first_container.end(), functor);
std::for_each(your_second_container.begin(), your_second_container.end(), functor);
std::cout<<"The sum of all the elements is: "<<functor.sum<<std::endl;

  1. Actually, as R Samuel Klatchko pointed out below, they can support multiple independent states, one for each functor instance:
    A slightly more precise statement is that functors can support multiple independent states (functions can support a single state via statics/globals which is neither thread-safe nor reentrant).
    Functors enables you to use even more complicated states, for example a shared state (static fields) and a private state (instance fields). However this further flexibility is rarely used.
Matteo Italia
A slightly more precise statement is that functors can support multiple independent states (functions can support a single state via statics/globals which is neither thread-safe nor reentrant).
R Samuel Klatchko
Surely you mean that function pointers are harder to optimize and inline? The way it's written now, it's a bit unclear.
jalf
I meant that function pointers are harder to optimize and inline; it doesn't seem unclear to me, "that" refers to the last phrase of the preceding sentence, i.e. "function pointers". However if you want to suggest a better phrasing I'll be glad to edit. :)
Matteo Italia
Just remember that you normally functors are supposed to behave like pure functions. See Scott Myers' Effective STL Item #39: `Make predicates pure functions`.
Billy ONeal
It's related just to the fact that many algorithms (e.g. sorting algorithms) rely on the fact that the same function called with the same parameters yields the same result, or is there anything else behind it?
Matteo Italia
+1  A: 

A function object is a function that is also an object, i.e. it has state. Normal functions generally do not have state. They may emulate having state by accessing global variables, but then the state is shared across all invocations.

Peter Alexander
+1  A: 

The idea of encapsulating a function as an object dates back to Lisp and Smalltalk. The C++ idea of functor was a chapter in Jim Coplien's book Advanced C++ Programming Styles and Idioms in 1991. STL used the idiom and further popularized it.

Bob Lied