c++When to use functors over lambdas

Is there ever a situation where it makes more sense to create a functor than to use a lambda?

I know my question is effectively the reverse of when to use a lambda over a functor, but I can't think of a situation in practice where a functor would be preferred over a lambda. Any thoughts on this?

A lambda is a functor - just defined with a shorter syntax.

The problem is that this syntax is limited. It doesn't always allow you to solve a problem in the most efficient and flexible way - or at all. Until C++14, the operator() couldn't even be a template.

Furthermore, a lambda has exactly one operator(). You can't provide several overloads to distinguish between, say, the types of the arguments:

struct MyComparator
{
    bool operator()( int a, int b ) const {return a < b;}
    bool operator()( float a, float b ) const {return /*Some maths here*/;}
};

.. or value category of the object argument (that is, the closure object that is called). You can also not define special member functions, including constructors and destructors - what if a functor shall be responsible for resources?

Another problem with lambdas is that they cannot be recursive. Of course, normal functions (including operator functions) can be.

Also consider that lambdas are unhandy to use as comparators for associative containers or deleters for smart pointers: You can't directly pass the closure type as a template argument and need to construct the containers member from another closure object. (Closure types don't have a default constructor!). For a block-scope map that isn't too much of a hassle:

auto l = [val] (int a, int b) {return val*a < b;};
std::map<int, int, decltype(l)> map(l);

Now, what happens if your map is a data member? What template argument, what initializer in the constructors initialization list? You'd have to use another static data member - but since you have to define it outside the classes definition that is arguably ugly.

To sum up: Lambdas aren't useful for more complex scenarios because they weren't made for them. They provide a short and concise way of creating simple function objects for correspondingly simple situations.

I would consider using a functor over a lambda when I

  • want more than one instance.
  • have to do advanced resource handling.
  • need to refer to the functor as a type. For example, to pass it as a template parameter.
  • (related) can give a meaningful and generally useful name to the type (as opposed to the instance).
  • find that the logic can be written cleaner when split up into sub-functions. In a lambda, we have to write everything into a single function.

I could think of two cases:

  1. When functor carries internal state, thus there is a non-trivial life time issue with the functor. It keeps "something" between the uses

  2. When you have to use same code all over the place, writing and keeping it as a functor in its own header might be a good idea from maintenance point-of-view

A lambda can't be used in an unevaluated context. A particularly contrived example is stolen from Shafik's answer:

  1. In many cases it just useless since each lambda has a unique type, the hypothetical example given:

    template<typename T, typename U>
    void g(T, U, decltype([](T x, T y) { return x + y; }) func);
    
    g(1, 2, [](int x, int y) { return x + y; });
    

    The type of the lambda in the declaration and the call are
    different(by definition) and therefore this can not work.

So even a lambda with identical syntax cannot be used in place of another. A functor will work in this case.

Related Articles
  • 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
  • I created a macro that conveniently builds lambda functions using which I can iterate through tensor objects in a library that I wrote. However, nesting these macros seemed to cause GCC to undergo an internal segmentation fault. Upon expanding the co
  • This question already has an answer here: return statement vs exit() in main() 7 answers I was wondering when should I use exit() function over return statement. I can end the program with either of the following statements: exit(0); or return; Which
  • I have some confusion between <link> and <a>. I know that in order to add CSS to an HTML document we use the ``` tag, for example: <link type="text/css" rel="stylesheet" href="/spinner/styles.css?ln=css" />
  • What is the difference between std::array and std::vector? When do you use one over other? I have always used and considered std:vector as an C++ way of using C arrays, so what is the difference? std::array is just a class version of the classic C ar
  • This question already has an answer here: When to use LinkedList over ArrayList? 25 answers I see that there are a ton of generic data structures provided in Java. They all implement List, so they can be used almost interchangeably, but when would I
  • I'm testing a code from the book C++ Concurrency in Action. Basically, it uses multi-thread to implement the same function as std::accumulate. As the following shows, I tried to use lambda in place of functor, but my code gave wrong results. The vari
  • I have seen samples of closure from - http://stackoverflow.com/questions/36636/what-is-a-closure Can anyone provide simple example of when to use closure? Specifically, scenarios in which closure makes sense? Lets assume that the language doesn't hav
  • I've searched around and haven't really found a clear answer as to when you'd want to use .First and when you'd want to use .FirstOrDefault with LINQ. When would you want to use .First? Only when you'd want to catch the exception if no results where
You Might Also Like