函数返回lambda表达式

Bar*_*ski 85 c++ lambda function c++11

我想知道是否可以在C++ 11中编写一个返回lambda函数的函数.当然一个问题是如何声明这样的功能.每个lambda都有一个类型,但是这种类型在C++中是不可表达的.我不认为这会奏效:

auto retFun() -> decltype ([](int x) -> int)
{
    return [](int x) { return x; }
}
Run Code Online (Sandbox Code Playgroud)

这不是:

int(int) retFun();
Run Code Online (Sandbox Code Playgroud)

我不知道从lambdas到函数指针或类似函数的任何自动转换.手工制作函数对象并返回它的唯一解决方案是什么?

Sea*_*ean 95

你不需要一个手工制作的函数对象,只需使用std::function,lambda函数可以转换为:

std::function<int (int)> retFun() {
    return [](int x) { return x; };
}
Run Code Online (Sandbox Code Playgroud)

  • 咄!我喜欢StackOverflow.研究该主题需要花费更长的时间,然后在StackOverflow上得到答案.谢谢肖恩! (6认同)
  • 这将导致在`std :: function`的构造函数中进行内存分配. (4认同)
  • @Maxim Yegorushkin std :: function有移动语义加上它可以使用自定义分配器,而C++ 0x工作草案有这些注释:"[注意:鼓励实现避免为小型可调用对象使用动态分配的内存,例如,其中f的目标是一个只包含对象和成员函数指针的指针或引用的对象.-end note]"所以基本上你不能对特定实现使用的分配策略做出很多假设,但你应该能够无论如何要使用你自己的(池化)分配器. (2认同)
  • 请记住,`std::function` 使用类型擦除,这意味着在调用 `std::function` 时进行虚函数调用的成本。如果返回的函数将用于紧密的内部循环或其他轻微低效问题的上下文,则需要注意一些事项。 (2认同)

use*_*498 29

对于这个简单的例子,你不需要std::function.

从标准§5.1.2/ 6开始:

没有lambda-capturelambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.

因为你的函数没有捕获,这意味着lambda可以转换为指向类型函数的指针int (*)(int):

typedef int (*identity_t)(int); // works with gcc
identity_t retFun() { 
  return [](int x) { return x; };
}
Run Code Online (Sandbox Code Playgroud)

这是我的理解,如果我错了,请纠正我.

  • 是的,这条规则的最终措辞对VC2010来说太迟了. (3认同)

dzh*_*oev 20

您可以从其他lambda函数返回lambda函数,因为您不应该显式指定lambda函数的返回类型.只需在全局范围内编写类似的内容:

 auto retFun = []() {
     return [](int x) {return x;};
 };
Run Code Online (Sandbox Code Playgroud)

  • 只有当外部lambda只包含return语句时才会出现这种情况.否则,您必须指定返回类型. (2认同)
  • 这是最好的答案,因为它不需要std :: function的运行时多态性,并允许lambda有一个非空的捕获列表,但是我会使用**const**auto fun = ... (2认同)
  • @BartoszMilewski 自 C++14 以来就不是真的。 (2认同)

Ant*_*all 15

虽然这个问题专门询问了C++ 11,但是为了其他偶然发现并且可以访问C++ 14编译器的人,C++ 14现在允许推导出普通函数的返回类型.因此,只需-> decltype在函数参数列表后面删除...子句,就可以根据需要调整问题中的示例.

auto retFun()
{
    return [](int x) { return x; }
}
Run Code Online (Sandbox Code Playgroud)

但请注意,如果return <lambda>;函数中出现多个,则无法使用此功能.这是因为对返回类型推导的限制是所有返回语句必须返回相同类型的表达式,但编译器为每个lambda对象赋予其自己的唯一类型,因此return <lambda>;表达式将各自具有不同的类型.

  • 为什么要提到c ++ 14的推导类型但省略多态lambda?`auto retFun(){return [](auto const&x){return x; }; }` (3认同)