Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use functors over functions?

Tags:

c++

functor

stl

Compare

double average = CalculateAverage(values.begin(), values.end()); 

with

double average = std::for_each(values.begin(), values.end(), CalculateAverage()); 

What are the benefits of using a functor over a function? Isn't the first a lot easier to read (even before the implementation is added)?

Assume the functor is defined like this:

class CalculateAverage { private:    std::size_t num;    double sum; public:     CalculateAverage() : num (0) , sum (0)    {    }     void operator () (double elem)     {       num++;        sum += elem;    }     operator double() const    {        return sum / num;    } }; 
like image 639
DanDan Avatar asked Jun 23 '11 09:06

DanDan


People also ask

What is the difference between a function and a functor?

A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.

What is the difference between a functor and a function pointer?

A function pointer allows a pointer to a function to be passed as a parameter to another function. Function Objects (Functors) - C++ allows the function call operator() to be overloaded, such that an object instantiated from a class can be "called" like a function.

How does a functor work?

A functor (or function object) is a C++ class that acts like a function. Functors are called using the same old function call syntax. To create a functor, we create a object that overloads the operator(). The line, MyFunctor(10); Is same as MyFunctor.

Are functors part of STL?

Overview. Function objects (also called functors) are an STL feature that you may not employ immediately when you start using the STL.


2 Answers

At least four good reasons:

Separation of concerns

In your particular example, the functor-based approach has the advantage of separating the iteration logic from the average-calculation logic. So you can use your functor in other situations (think about all the other algorithms in the STL), and you can use other functors with for_each.

Parameterisation

You can parameterise a functor more easily. So for instance, you could have a CalculateAverageOfPowers functor that takes the average of the squares, or cubes, etc. of your data, which would be written thus:

class CalculateAverageOfPowers { public:     CalculateAverageOfPowers(float p) : acc(0), n(0), p(p) {}     void operator() (float x) { acc += pow(x, p); n++; }     float getAverage() const { return acc / n; } private:     float acc;     int   n;     float p; }; 

You could of course do the same thing with a traditional function, but then makes it difficult to use with function pointers, because it has a different prototype to CalculateAverage.

Statefulness

And as functors can be stateful, you could do something like this:

CalculateAverage avg; avg = std::for_each(dataA.begin(), dataA.end(), avg); avg = std::for_each(dataB.begin(), dataB.end(), avg); avg = std::for_each(dataC.begin(), dataC.end(), avg); 

to average across a number of different data-sets.

Note that almost all STL algorithms/containers that accept functors require them to be "pure" predicates, i.e. have no observable change in state over time. for_each is a special case in this regard (see e.g. Effective Standard C++ Library - for_each vs. transform).

Performance

Functors can often be inlined by the compiler (the STL is a bunch of templates, after all). Whilst the same is theoretically true of functions, compilers typically won't inline through a function pointer. The canonical example is to compare std::sort vs qsort; the STL version is often 5-10x faster, assuming the comparison predicate itself is simple.

Summary

Of course, it's possible to emulate the first three with traditional functions and pointers, but it becomes a great deal simpler with functors.

like image 130
Oliver Charlesworth Avatar answered Sep 17 '22 06:09

Oliver Charlesworth


Advantages of Functors:

  • Unlike Functions Functor can have state.
  • Functor fits into OOP paradigm as compared to functions.
  • Functor often may be inlined unlike Function pointers
  • Functor doesn't require vtable and runtime dispatching, and hence more efficient in most cases.
like image 22
Alok Save Avatar answered Sep 17 '22 06:09

Alok Save