C++ 使用lambda在if-else语句中返回布尔值
这是我的密码:C++ 使用lambda在if-else语句中返回布尔值,c++,lambda,C++,Lambda,这是我的密码: int main(int argc, char** argv) { bool gg; if( [&]()->decltype(gg){ return false; //try changing this to true or false and you'll get the same result. } ){ std::cout<<"all even"<<std::endl; }e
int main(int argc, char** argv) {
bool gg;
if( [&]()->decltype(gg){
return false; //try changing this to true or false and you'll get the same result.
} ){
std::cout<<"all even"<<std::endl;
}else {
std::cout<<"all odd"<<std::endl;
}
return 0;
}
int main(int argc,char**argv){
布尔gg;
if([&]()->decltype(gg){
return false;//尝试将其更改为true或false,您将得到相同的结果。
} ){
std::cout您不计算lambda,只需检查对象:
int main(int argc, char** argv) {
bool gg;
if( [&]()->decltype(gg){
return false; //try changing this to true or false and you'll get the same result.
}() == true){
std::cout<<"all even"<<std::endl;
}else {
std::cout<<"all odd"<<std::endl;
}
return 0;
}
int main(int argc,char**argv){
布尔gg;
if([&]()->decltype(gg){
return false;//尝试将其更改为true或false,您将得到相同的结果。
}()==真){
标准::cout
5.1.2 Lambda表达式
6没有lambda捕获的lambda表达式的闭包类型具有公共非虚拟非显式常量转换
函数到指针,指向具有相同参数和返回的函数
类型作为闭包类型的函数调用运算符。返回的值
通过该转换函数,应为函数的地址,
调用时,与调用闭包类型的
函数调用操作符
这正是在您的案例中发生的情况。您忘记调用闭包对象的()
运算符。相反,您在if
中使用闭包对象本身作为条件
由于闭包对象不捕获任何内容,根据5.1.2/6,它隐式转换为普通函数指针类型bool(*)(
),因此您的对象隐式转换为函数指针。由于指针不为空,因此它在if
下充当true
换句话说,编译器将按照以下方式解释代码
bool gg;
auto lf = [&]() -> decltype(gg) { return false; };
bool (*f)() = lf;
if (f) {
...
如果使lambda函数实际捕获某些内容(例如,将return false;
替换为return gg;
),则原始代码将立即无法编译
注意:正如您在下面的评论中所读到的,[&]
的存在显然应该为您的lambda禁用5.1.2/6。但显然,您的编译器对5.1.2/6的处理更为宽松,并查找实际捕获,而不是简单地检查非[]
capture子句。如果使用命名函数编写相同的代码:if(returnFalse){…}
你会期望什么?如果你不调用函数,你怎么期望它返回值?…我不太明白为什么会编译它。一定是另一个gcc扩展。我投票结束这个问题,因为它显示出缺乏研究和对语言基础的理解。@dyp不一定,你对函数指针也可以做同样的事情…它从函数指针隐式转换到bool,这是非常危险的。VS实际上拒绝编译该代码。它不是已经得到了评估,因为它返回了true或false吗?@CarloBrew评估函数与调用函数不同。它的错误与:bool f();if(f){
而不是if(f()){
哦,好吧,我忘了lambda不会自动调用,除非它类似于std transform。我添加了==true,因为我觉得这更清楚,但真正缺少的是括号。这会计算lambda并询问“返回值为真吗?”如果没有它,则表示“此lambda对象是否可转换为布尔值?此布尔值是否为真?”这是不同的,并且不会计算lambda。@CarloBrew它们永远不会“自动调用”。高阶函数(例如std::transform()
)也显式调用提供的回调/转换函数。OOoo好的。难怪它得到了计算,我没有得到任何错误。@dyp这一段并不排除捕获lambda进行转换;它只定义了不捕获lambda的行为。好的,再次检查:我是对的,这个lambda不能转换为有趣的Action指针。它确实有一个捕获,clang++对此表示不满。g++接受它,这是一个扩展。也就是说,捕获默认语法上是lambda捕获。因此,此lambda确实有lambda捕获,并且不能转换为函数指针。@mattmcnab请参见p3。不允许实现添加此类转换。您可以通过SFINAE反射观察转换是否存在。