Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++: Multiple assignment inside if block syntax for short circuiting [duplicate]

I wanted to be able to do multiple assignments in an if block and short-circuit if the first one fails. However, this does not compile and says, expected primary-expression before ‘auto’

#include <iostream>
#include <optional>

std::optional<int> foo()
{
    return 0;
}

int main() {
    if (auto a = foo() && auto b = foo())
    {
        std::cout << "a = " << *a << ", b = " << *b << std::endl;
    }
}

The following works though and does what I want.

    if (auto a = foo())
    {
      if (auto b = foo()) {
        std::cout << "a = " << *a << ", b = " << *b << std::endl;
      }
    }

But is there a way for me to use the syntax in the first one? Using parenthesis to surround the expressions does not work.

like image 694
Mochan Avatar asked Nov 01 '25 02:11

Mochan


2 Answers

Since C++17, you could write

if (decltype(foo()) a, b; (a = foo()) && (b = foo()))
{
    std::cout << "a = " << *a << ", b = " << *b << std::endl;
}

But if you want to see the short circuit in action, you should change the condition:

#include <iostream>
#include <optional>

std::optional<int> foo()
{
    std::cout << "foo called.\n";
    return 1;
}

int main()
{
    if (decltype(foo()) a, b; (a = foo()) or (b = foo()))
    {
        // For exposition only            ^^
        std::cout << "a = " << *a << ", b = " << *b << std::endl;
        // Note that, now, this is UB            ^^
    }
}

Compare the output of this

foo called.
a = 1, b = 0

Versus the former.

like image 109
Bob__ Avatar answered Nov 03 '25 19:11

Bob__


It has nothing to do with auto. Declarations cannot be part of an expression. You can either use an expression or a single declaration inside an if statement.

So even this will not compile:

#include <iostream>

int foo()
{
    return 0;
}

int main()
{
    if (int a = foo() && int b = foo())
    {
        std::cout << "a = " << a << ", b = " << b << std::endl;
    }
    return 0;
}

Edit: In C++17 you can have an initializer statement before the condition statement, like so: if (auto a = foo(), b = foo(); a && b). However that will not give you short circuiting.

like image 36
Max Vollmer Avatar answered Nov 03 '25 17:11

Max Vollmer