8

I have code below and it reports "auto is not allowed here"

//GeSettings() returns boost::optional<ValueType> and could be empty

if((auto ret = GetSettings(InputField)) && ShouldWeDoThis())
{
   do something with ret;
}

but changing as below if fine.

if(auto ret = GetSettings(InputField))
{
    if(ShouldWeDoThis())
    {
        do something with ret;
    }
}

The reason behind could be silly buy may I ask why? I am using Visual Studio 2017

Bing Lan
  • 1,121
  • 1
  • 13
  • 26
  • 1
    If you are using Visual Studio 2017, do you use the new C++17 features? Or are you restricted to C++14? – DeiDei Dec 14 '17 at 23:56
  • @DeiDei good point, it's actually still 2013 compiler, pushed to upgrade to 2017 – Bing Lan Dec 15 '17 at 00:00
  • 4
    C++17 allows `if (auto ret = GetSettings(InputField); ret && ShouldWeDoThis())`. – Jarod42 Dec 15 '17 at 00:08
  • Once you have that, the idiomatic way to handle this is with `if (auto ret = GetSettings(InputField); ret && ShouldWeDoThis()) { do something with ret; }`. This initialization is allowed in `if` and `switch`, and is analogous to the initialization section of a `for` loop. Note that the value of `ret` isn’t necessarily checked in the `if` statement; you still need to do that yourself. – Daniel H Dec 15 '17 at 00:11
  • Possible duplicate of [C++, variable declaration in 'if' expression](https://stackoverflow.com/questions/7836867/c-variable-declaration-in-if-expression) – cpplearner Dec 15 '17 at 09:54

1 Answers1

7

Your first version:

if((auto ret = GetSettings(InputField)) && ShouldWeDoThis())

is not allowed under any c++ standard, as you can not have declarations in expressions.

§6.4 (from c++11) Selection statements defines what an if statement looks like:

  • if (condition) statement
  • if (condition) statement else statement

Further down condition is defined:

  • expression
  • attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
  • attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list

This allows us to write things like

if (auto ret = Foo())

However, in c++17 and forward, the definition changed (and moved to §9.4):

  • if constexpropt (init-statementopt condition) statement
  • if constexpropt (init-statementopt condition) statement else statement

We can now write things like:

if (auto ret=Foo(); ret && Bar())

Which should be useful for your purpose.

sp2danny
  • 7,488
  • 3
  • 31
  • 53
  • And to extend the answer a bit, it's possible to do more than one init-statement: `if (auto stream = wstream.lock(); auto delegate = stream->_delegate.lock())`. I.e. useful when dealing with multiple `std::weak_ptr`s that need to be locked in order to execute the conditional block. – LB2 Mar 31 '21 at 16:42