4

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.

Mochan
  • 1,329
  • 1
  • 13
  • 27

3 Answers3

6

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.

Bob__
  • 12,361
  • 3
  • 28
  • 42
2

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.

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43
2

The only way I see is that you reformulate (without declaring the variables inside the if condition):

#include <iostream>
#include <optional>

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

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

See a working example here please.


Since c++17 you can even do the variable declarations inside the if condition like this:

if (std::optional<int> a , b; (a = foo()) && (b = foo()))

Though usage of auto isn't possible in that case.

Another live demo.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190