Lambda是在函数/方法中创建可重用代码而不会污染父类的一种很棒的方法。它们在大多数时候都是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;
}
显然这是一个过于简单的例子,但基本的前提是我在不同的变量上反复执行相同的检查,我认为封装检查和相关的退出更具可读性。不过,我知道macros aren't very safe,特别是当他们变得非常复杂时。但是,据我所知,尝试做等效的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做到这一点?或者我错过了一些替代解决方案?
修改:我认为returning from inside a macro is generally a bad idea除非significant precautions are taken。我只是想知道是否可能。
答案 0 :(得分:3)
你是对的 - 没有办法从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);
};
答案 1 :(得分:1)
没有更好的方法来做这个,而不仅仅是使用lambda的返回值,然后使用调用函数中的return
。宏是这样的。
就像C ++一样,这是退出使用另一个条件确定是否退出的函数的惯用方法。
答案 2 :(得分:1)
有没有办法用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
}
答案 3 :(得分:0)
不是C ++ 11,但人们已经破解了C ++ 2a协程,基本上就是这样做了。
看起来有点像:
co_await check_range(foo);
其中co_await
关键字表示在某些情况下,此协程可能会提前返回不完整的结果。在您的情况下,这个不完整的结果将是不可再造的错误。
我看到的游戏是选项,并且需要使用共享的ptr,但事情可能会在标准化之前得到改善。