Return 从 lambda 内部调用函数
Return from calling function inside lambda
Lambda 是在 function/method 中创建可重用代码而不污染父级 class 的绝佳方式。在大多数情况下,它们是 C 样式宏的非常实用的替代品。
但是,我似乎无法用 lambda 复制宏中的一点语法糖,那就是从包含函数中退出的能力。例如,如果我在检查一系列 int
的范围时需要 return,我可以使用宏轻松地做到这一点:
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 unless significant precautions are taken。我只是想知道这是否可能。
没有比使用 lambda 的 return 值然后调用函数中的 return
更好的方法了。宏是新的。
在 C++ 中,这是退出函数的惯用方式,该函数使用另一个条件来确定是否退出。
你是对的——无法从 lambda 内部的调用者 return。由于可以捕获并存储 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);
};
不是 C++11,但人们已经破解了 C++2a 协程来基本上做到这一点。
看起来有点像:
co_await check_range(foo);
其中 co_await
关键字表示在某些情况下,此协程可能会 return 提早得到不完整的结果。在您的情况下,这个不完整的结果将是不可恢复的错误。
我看到的游戏是可选的,需要使用共享 ptr,但在标准化之前情况可能会有所改善。
Is there a way to do this with a 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 是在 function/method 中创建可重用代码而不污染父级 class 的绝佳方式。在大多数情况下,它们是 C 样式宏的非常实用的替代品。
但是,我似乎无法用 lambda 复制宏中的一点语法糖,那就是从包含函数中退出的能力。例如,如果我在检查一系列 int
的范围时需要 return,我可以使用宏轻松地做到这一点:
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 unless significant precautions are taken。我只是想知道这是否可能。
没有比使用 lambda 的 return 值然后调用函数中的 return
更好的方法了。宏是新的。
在 C++ 中,这是退出函数的惯用方式,该函数使用另一个条件来确定是否退出。
你是对的——无法从 lambda 内部的调用者 return。由于可以捕获并存储 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);
};
不是 C++11,但人们已经破解了 C++2a 协程来基本上做到这一点。
看起来有点像:
co_await check_range(foo);
其中 co_await
关键字表示在某些情况下,此协程可能会 return 提早得到不完整的结果。在您的情况下,这个不完整的结果将是不可恢复的错误。
我看到的游戏是可选的,需要使用共享 ptr,但在标准化之前情况可能会有所改善。
Is there a way to do this with a 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
}