Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "constructor-way" of declaring variable in "for-loop" allowed but in "if-statement" not allowed? [duplicate]

Possible Duplicate:
Why can't variables defined in a conditional be constructed with arguments?

Consider this simple example:

/*1*/ int main() {
/*2*/   for (int i(7); i;){break;} 
/*3*/   if (int i(7)) {}
/*4*/ }

Why line-2 compiles just fine, whilst line-3 gives the error? This is little strange to me why if-statement is in this aspect treated worse than for-loop?

If this is compiler specific - I tested with gcc-4.5.1:

prog.cpp: In function 'int main()': prog.cpp:3:7: error: expected primary-expression before 'int' prog.cpp:3:7: error: expected ')' before 'int'

I was inspired by this question

[UPDATE]

I know this compiles just fine:

/*1*/ int main() {
/*2*/   for (int i = 7; i;){break;} 
/*3*/   if (int i = 7) {}
/*4*/ }

[UPDATE2]

It seems to be purely academic question - but this could be extremely important for such types as std::unique_ptr<> which cannot be copied:

#include <memory>
int main() {
  if (std::unique_ptr<int> i = new (std::nothrow) int(7)) {
  }
  if (std::unique_ptr<int> i(new (std::nothrow) int(7))) {
  }
}

Neither of these two kinds are allowed. Not sure about new C++11 syntax {}?

like image 910
PiotrNycz Avatar asked Sep 29 '12 21:09

PiotrNycz


2 Answers

The C++ standard doesn't provide a rationale but I would suspect that using the constructor notation could cause some inconsistencies. For example, since function declarations aren't allowed in the if statement, the most vexing parse would actually mean what was intended. For example:

int f();        // function declaration (simple form or the most vexing parse)
if (int f()) {  // illegal in C++ but, when allowed, would be a zero-initialized int
}

In C++ 2011 you can use brace-initialization:

if (int x{f()}) {
    ...
}

Unfortunately, brace-initialization doesn't always mean the same thing as using constructor notation (I think it's called direct-initialization).

With respect to the update: you can use one of these:

if (std::unique_ptr<int> p = std::unique_ptr<int>(new int(1))) { ... }
if (auto p = std::unique_ptr<int>(new int(2))) { ... }
if (std::unique_ptr<int>{new int(3)}) { ... }

It seems there are plenty of options :-)

like image 162
Dietmar Kühl Avatar answered Oct 14 '22 19:10

Dietmar Kühl


In terms of syntax, the reason is simple.

The first element of the for statement are statements. Statements can create variables as well as initialize them. The if conditional is a condition. The spec does define that a condition can create a variable, but only by = initialization.

Be glad the spec even allows you to create variables in an if at all. It has to have special grammar to even allow that ("condition" being different from "expression"), and that was probably something inherited from C.

That being said, C++11 does define a condition as being able to initialize a declaration with a braced-init-list (spec-speak for "initializer list"). So it should be legal. But since VS2012 doesn't support initializer lists yet...

like image 43
Nicol Bolas Avatar answered Oct 14 '22 20:10

Nicol Bolas