[Development] RFC: lambda or lambda return from lambda?

Marc Mutz marc.mutz at kdab.com
Mon Feb 1 11:08:54 CET 2016


Hi,

We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about the 
result.

E.g. (not picking on Anton here, I have done the same before):

 auto firstEqualsName = [&name](const QPair<QByteArray, QByteArray> &header)
 {
      return qstricmp(name.constData(), header.first) == 0;
 };
 fields.erase(std::remove_if(fields.begin(), fields.end(),
                             firstEqualsName),
              fields.end());

This is one way to write a unary predicate. But it hides the fact that the 
predicate depends on the parameter 'name' (an argument to the function this 
lambda is defined in).

With classical function objects, one would have written - at the call site:

 fields.erase(std::remove_if(fields.begin(), fields.end(),
                             FirstEquals(name)),
              fields.end());

See the difference?

Now, we don't want to go back and write function objects for one-time use, but 
it would be nice to have this explicit syntax, would it not?

One way to have this with lambdas is to write a lambda that returns a lambda. 
We can do this, because auto return type deduction works for lambdas already 
in C++11, unlike for normal functions. With this, the above would become (hold 
tight):

  auto firstEquals = [](const auto &name) {
    return [&name](auto header) { return qstricmp(header.first, name) == 0; };
  }

where I used auto and dropped the const-& argument passing only for 
exposition, to get it onto a single line.

 fields.erase(std::remove_if(fields.begin(), fields.end(),
                             firstEquals(name)),
              fields.end());

So, where to put the ugliness: on the definition of the lambda, or the call 
site? (Note that "if you use this lambda more than once, then X" is not a good 
answer, because you shouldn't use lambdas more than once. But with the lambda-
returning-lambda, you could actually reuse them:

// at global scope:

  auto firstEquals = [](const auto &name) {
    return [&name](auto header) { return qstricmp(header.first, name) == 0; };
  }

  // use in several functions - always the same type

Whereas without the outer lambda, each use would create a new type, and 
potentially duplicate code (same problem as QStringLiteral, and the same 
soultion, really: wrap them in a function, except for lambdas, because of the 
unnameable return type, we need to use another lambda instead of a classical 
function).

So, which one to use?

Thanks,
Marc

-- 
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts



More information about the Development mailing list