为什么要在 C++ lambda 前面放置一元加 (+) 运算符?

Ale*_*lex 17 c++ lambda

我发现在 C++ 中我们可以+在 lambda 函数中使用+[]{} 文章中的示例:

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

lambda中+号的主要思想

您可以通过在前面添加 + 来强制编译器将 lambda 生成为函数指针而不是闭包,如上所示。

但是在 lambda 中使用“+”有什么好处呢?您能否提供示例或将我链接到解释?

Swi*_*Pie 11

它不是 lambda 的特性,更多的是隐式类型转换的特性。

发生的情况源于这样一个事实:无捕获 lambda可以隐式转换为指向与 lambda 具有相同签名的函数的指针operator()。+[]{}是一个表达式,其中一元+ 是 no-op ,因此表达式的唯一合法结果是指向函数的指针。

结果auto funcPtr将是指向函数的指针,而不是 lambda 表达式返回的匿名类型的对象实例。在提供的代码中没有太多优势,但在类型无关的代码中可能很重要,例如decltype使用某种表达式的地方。例如

#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"); 
}  
Run Code Online (Sandbox Code Playgroud)

请注意,您可以执行相同的操作foo: std::is_same<T, decltype(+foo)> {};

尽管某些平台可能不支持这一点,因为它们本质上可能具有各种具有不同调用约定的函数指针,并且表达式会不明确。


Jar*_*d42 6

在模板中使用函数指针对抗 lambda 的优点之一可能是减少模板实例化的数量。

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


int main()
{
    f([](){});  // f<lambda_1>
    f([](){});  // f<lambda_2>
    f(+[](){}); // f<void(*)()>
    f(+[](){}); // f<void(*)()>
}
Run Code Online (Sandbox Code Playgroud)

  • 将特定 lambda 类型推断为模板参数的优点是可以内联和优化 lambda 的调用。这就是 C++ 通常如何从函数式代码中获得与显式手写循环相同或更好的性能。 (3认同)