2

Here is my code:

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;
}

It's just simple, i have an if else statement and a lambda function inside it that checks the condition. I don't know if it's the code or compiler but even if i change false to true and vice versa, i get the same result. I am using Dev CPP. What's wrong with my code?

12
  • 2
    well if you wrote the same code with a named function: if (returnFalse) { …} what would you expect? If you don't call the function, how do you expect a return value out of it? Commented Jul 24, 2015 at 5:45
  • ... I don't quite understand why this even compiles. Must be another gcc extension. Commented Jul 24, 2015 at 5:45
  • I'm voting to close this question as off-topic because it shows lack of research and of understanding of fundamentals of the language. Commented Jul 24, 2015 at 5:47
  • @dyp not necessarily, you can do the same thing with function pointers… Commented Jul 24, 2015 at 5:48
  • It does implicit cast from function pointer to bool, which is pretty dangerous. VS actually refuses to compile that code. Commented Jul 24, 2015 at 5:48

2 Answers 2

6

5.1.2 Lambda expressions

6 The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

That is exactly what happens in your case. You forgot to invoke your closure object's () operator. Instead you used the closure object itself as a condition in if.

Since your closure object does not capture anything, per 5.1.2/6 it is implicitly convertible to plain function pointer type bool (*)(). And so your object got implicitly converted to a function pointer. Since the pointer is not null, it acts as true under if.

On other words, your code is interpreted by the compiler in the following way

bool gg;
auto lf = [&]() -> decltype(gg) { return false; };

bool (*f)() = lf;
if (f) {
  ...

If you make your lambda function actually capture something (e.g. replace return false; with return gg;), your original code will immediately fail to compile.

P.S. As you can read in the comments below, the very presence of [&] apparently should have disabled 5.1.2/6 for your lambda. But apparently your compiler treats 5.1.2/6 more loosely and looks for actual captures instead of simply checking for presence of non-[] capture clause.

Sign up to request clarification or add additional context in comments.

7 Comments

OOoo alright. no wonder it got evaluated and i didnt get any error.
@dyp this paragraph doesn't exclude capturing lambdas from having the conversion; it only defines the behaviour for non-capturing lambdas.
Ok, checked again: I was right, this lambda is not convertible to a function pointer. It does have a capture, and clang++ complains about it. g++ accepts it, which is an extension.
That is, a capture-default grammatically is a lambda-capture. Hence, this lambda does have a lambda-capture and is not convertible to a function pointer. coliru.stacked-crooked.com/a/5b938c774611398a
@MattMcNabb See p3. An implementation is not allowed to add such a conversion. You can observe whether or not the conversion exists via SFINAE-reflection.
|
5

You don't evaluate the lambda, you just check the object:

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;
}

edit: Ideone code https://ideone.com/yxloQf

5 Comments

Doesn't it get evaluated already since it returned a true or false?
@CarloBrew evaluating a function is different to calling it. It's the same error as: bool f(); if ( f ) { instead of if ( f() ) {
Oh alright, i forgot lambda's aren't automatically called unless it's something like std transform.
Just to be clear: I added == true because I feel this is clearer but what was really missing was the parenthesis after the brackets. This evaluates the lambda and ask "is the return value true?" without it it means "does this lambda object is convertible to boolean and is this boolean true?" which is different and does not evaluate the lambda.
@CarloBrew they are never "called automatically". Higher-order functions (such as std::transform()) call the supplied callbacks/transformation functions explicitly as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.