从 lambda 中的调用函数返回

Return from calling function inside lambda

本文关键字:函数 返回 调用 lambda      更新时间:2023-10-16

Lambdas是一种很棒的方法,可以在函数/方法中创建可重用的代码,而不会污染父类。大多数时候,它们是 C 样式宏的非常实用的替代品。

但是,宏中有一点语法糖我似乎无法用 lambda 复制,那就是从包含函数退出的能力。例如,如果我需要在检查一系列int的范围时返回,我可以使用宏轻松完成:

const int xmin(1), xmax(5);
#define CHECK_RANGE(x) { if((x) < xmin || (x) > xmax) return false; }
bool myFunc(int myint) {
CHECK_RANGE(myint);
int anotherint = myint + 2;
CHECK_RANGE(anotherint);
return true;
}

显然这是一个过于简化的示例,但基本前提是我对不同的变量一遍又一遍地执行相同的检查,我认为封装检查和相关出口更具可读性。不过,我知道宏不是很安全,尤其是当它们变得非常复杂时。但是,据我所知,尝试执行等效的 lambda 需要像这样笨拙的额外检查:

const int xmin(1), xmax(5);
auto check_range = [&](int x) -> bool { return !(x < xmin || x > xmax); };
bool myFunc(int myint) {
if(!check_range(myint)) return false;
int anotherint = myint + 2;
if(!check_range(anotherint)) return false;
return true;
}

有没有办法用 lambda 做到这一点?还是我错过了一些替代解决方案?

编辑:我认识到,除非采取重大预防措施,否则从宏内部返回通常是一个坏主意。我只是想知道这是否可能。

你是对的 - 没有办法从 lambda 内部从调用方返回。由于可以从任意调用方内部捕获和存储 lambda 以供稍后调用,因此这样做会导致不可预测的行为。

class Foo
{
Foo(std::function<void(int)> const& callMeLater) : func(callMeLater) {}
void CallIt(int* arr, int count)
{
for (index = count; index--;)
func(count);
// do other stuff here.
}
std::function<void(int)> func;
};
int main()
{
auto find3 = [](int arr) 
{
if (arr == 3)
return_from_caller; // making up syntax here.
};
Foo foo(find3);
};

有没有办法用lambda做到这一点?

不完全像宏,但您的 lambda,而不是返回bool,可以throw特殊异常(例如,类型bool(

auto check_range
= [](int x) { if ( (x < xmin) || (x > xmax) ) throw bool{false}; };

而函数myFunc()可以截获这种特殊类型

bool myFunc (int myint)
{
try
{
check_range(myint);
int anotherint = myint + 2;
check_range(anotherint);
return true;
}
catch ( bool e )
{ return e; }
}

对于一个check_range()电话,这是(我想(一个坏主意;如果你有很多电话,我想可能会很有趣。

以下是完整的工作示例

#include <iostream>
constexpr int xmin{1}, xmax{5};
auto check_range
= [](int x) { if ( (x < xmin) || (x > xmax) ) throw bool{false}; };
bool myFunc (int myint)
{
try
{
check_range(myint);
int anotherint = myint + 2;
check_range(anotherint);
return true;
}
catch ( bool e )
{ return e; }
}
int main ()
{
std::cout << myFunc(0) << std::endl; // print 0
std::cout << myFunc(3) << std::endl; // print 1
std::cout << myFunc(7) << std::endl; // print 0
}

没有比只使用 lambda 的返回值然后从调用函数return更好的方法了。 宏就是为此而做的。

正如C++的那样,这是退出函数的惯用方式,该函数使用另一个条件来确定是否退出。

不是C++11,但人们已经破解了C++2a协程来基本上做到这一点。

它看起来有点像:

co_await check_range(foo);

其中co_await关键字指示在某些情况下,此协程可能会提前返回并显示不完整的结果。 在您的情况下,此不完整的结果将是不可恢复的错误。

我看到的玩法是可选的,并且需要使用共享 ptr,但在标准化之前情况可能会有所改善。