17

I found out that in C++ we can use + in lambda function +[]{} Example from the article:

#include <iostream>
#include <type_traits>
int main()
{
    auto funcPtr = +[] {};
    static_assert(std::is_same<decltype(funcPtr), void (*)()>::value);
}

The main idea of + sign in lambda

You can force the compiler to generate lambda as a function pointer rather than closure by adding + in front of it as above.

But what are advantages of using '+' in lambda? Could you please provide example or link me to the explanation?

user3840170
  • 26,597
  • 4
  • 30
  • 62
Alex
  • 562
  • 1
  • 6
  • 25

2 Answers2

11

It's not a feature of lambda and more is a feature of implicit type conversion.

What happens there is stemming from the fact that a captureless lambda can be implicitly converted to a pointer to function with same signature as lambda's operator(). +[]{} is an expression where unary + is a no-op , so the only legal result of expression is a pointer to function.

In result auto funcPtr would be a pointer to a function, not an instance of an object with anonymous type returned by lambda expression. Not much of advantage in provided code, but it can be important in type-agnostic code, e.g. where some kind of decltype expression is used. E.g.

#include <type_traits>

void foo(int);

template<class T>
struct is_foo : std::is_same<T, decltype(&foo)> {};

int main()
{
    auto foo1 = +[](int)->void {};
    auto foo2 = [](int)->void {};
    static_assert(is_foo<decltype(foo1)>::value, "foo1 is not like foo");
    static_assert(is_foo<decltype(+foo2)>::value, "+foo2 is not like foo");
    static_assert(is_foo<decltype(foo2)>::value, "foo2 is not like foo"); 
}  

Note that you can do same with foo: std::is_same<T, decltype(+foo)> {};

Albeit some platforms may not support that, because they inherently may have a variety of function pointers with different calling convention and the expression will be ambiguous.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
6

One advantage to use function pointer against lambda in template might be to reduce the number of template instantiation.

template <typename F>
void f(F func) { func(); }


int main()
{
    f([](){});  // f<lambda_1>
    f([](){});  // f<lambda_2>
    f(+[](){}); // f<void(*)()>
    f(+[](){}); // f<void(*)()>
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • ooh, right C++ now allows to use lambda like in template arguments even. Maybe it could be better for our sanity that it wouldn't. I sense birth of so many bugs related to *this* and millions of my brain cells scream in horror. – Swift - Friday Pie Dec 28 '21 at 15:34
  • Using lambda in template is so convenient. – Jarod42 Dec 28 '21 at 19:23
  • 3
    The advantage of inferring a specific lambda type as a template parameter is that invocation of the lambda can be inlined and optimized. This is how C++ often gets the same or better performance from functional-style code as from explicit hand-written loops. – Ben Voigt Dec 28 '21 at 20:00
  • @BenVoigt Through tracing the value and (if needed) function duplication it can nearly always be inlined and optimized. But yes, using a lambda makes it nearly guaranteed. – Deduplicator Dec 28 '21 at 20:24