嵌套的 lambda 函数

Nested lambda function

本文关键字:函数 lambda 嵌套      更新时间:2023-10-16

我有以下代码:

auto get_functor = [&](const bool check) {
return  [&](const foo& sr)->std::string {
if(check){
return "some string";
}
return "another string"
};
};
run(get_functor(true));

run函数签名:

void run(std::function<std::string(const foo&)> func);

我收到以下错误,这对我来说不太清楚:

error C2440: 'return' : cannot convert from 'main::<lambda_6dfbb1b8dd2e41e1b6346f813f9f01b5>::()::<lambda_59843813fe4576d583c9b2877d7a35a7>' to 'std::string (__cdecl *)(const foo &)'

附言我在 MSVS 2013 上

编辑:

如果我通过将auto替换为真实类型来编辑代码:

std::function<std::string(const foo&)> get_functor1 = [&](const bool check) {
return  [&](const foo& sr)->std::string {
if (check) {
return "some string";
}
return "another string";
};
};
run(get_functor1(true));

我收到另一个错误:

error C2664: 'std::string std::_Func_class<_Ret,const foo &>::operator
()(const foo &) const' : cannot convert argument 1 from 'bool' to
'const foo &'

这完全搞砸了!

我能够使用以下MVCE在VS 2013上重现相同的错误:

#include <iostream>
#include <functional>
#include <string>
struct foo {};
std::string run(std::function<std::string(foo const&)> f) {
return f(foo());
}
int main() {
auto get_functor = [&](bool const check) {
return [=](foo const&) -> std::string { // Line of the compiler error
if (check) {
return "CHECK!";
}
else {
return "NOT CHECK!";
}
};
};
std::cout << run(std::function<std::string(foo const&)>(get_functor(true)));
return 0;
}

然后我得到错误:

Error   1   error C2440: 'return' : cannot convert from 'main::<lambda_1bc0a1ec72ce6dc00f36e05599609bf6>::()::<lambda_4e0981efe0d720bad902313b44329b79>' to 'std::string (__cdecl *)(const foo &)'

问题在于 MSVC 无法处理返回的 lambda:当您不指定返回类型时,它会尝试将其衰减为常规函数指针。这失败了,因为您的 lambda 确实捕获了元素!

此外,您的修复是错误的,因为std::function<std::string(foo const&)>不是get_functor的类型,而是您要从中返回的类型。

直接在get_functor中强制嵌入到返回的 lambda 的std::function中将解决您的问题:

auto get_functor = [&](bool const check) -> std::function<std::string(foo const&)> {
return [=](foo const&) -> std::string {
if (check) {
return "some string";
} else {
return "another string";
}
};
};
std::cout << run(get_functor(true));

坦率地说,我有时想知道复杂的lambda是否值得费心。

将其分解为已知类型的函子对象将始终有效:

#include <functional>
#include <iostream>
#include <string>

struct foo
{
};
struct foo_functor{
foo_functor(bool check) : check(check) {}
std::string operator()(const foo&) const
{
if (check) {
return "some string";
}
return "another string";
}
const bool check;
};
auto make_foo_functor(bool check) -> foo_functor
{
return foo_functor { check };
}
void run(std::function<std::string(const foo&)> func)
{
foo f;
auto s = func(f);
std::cout << s << std::endl;
}
int main()
{
std::cout << "c++ version: " << __cplusplus << std::endl;
auto get_functor = [&](const bool check) -> foo_functor
{
return make_foo_functor(check);
};
run(get_functor(true));
}

从您的编辑来看,get_functor1是一个 lambda,它接受单个bool参数并返回另一个 lambda, 但是您尝试将get_functor1转换为此函数类型:

std::function<std::string(const foo&)>

这是不兼容的。相反,如果要避免auto类型扣除,则应使用:

std::function<std::function<std::string(const foo&)>(bool)>

也就是说,一个接受布尔值并返回另一个函数的函数,该函数接受const foo &并返回std::string

然后get_functor1变成:

std::function<std::function<std::string(const foo&)>(bool)> get_functor1 = [&](const bool check)
{
return  [&](const foo& sr)->std::string {
if (check) {
return "some string";
}
return "another string";
};
};