2

Why is this ok:

if(int i = 1) {
}

...whereas the following produces errors?

if((int i = 1)) {
}

Under g++ (4.4.5) the latter gives:

test.cpp:7: error: expected primary-expression before ‘int’
test.cpp:7: error: expected ‘)’ before ‘int’
test.cpp:9: error: expected ‘)’ before ‘else’
test.cpp:13: error: expected primary-expression before ‘}’ token
test.cpp:13: error: expected ‘;’ before ‘}’ token

Incidentally, the reason I'm asking is because of this answer: Seeing what class an object is

I'm trying to find a way to make the condition more readable. Usually, I would prefer, for example:

if((x = y) != 0) {

to

if(x = y) {

...since it's more readable and silences compiler 'comments' suggesting I might have used the wrong operator. If I'm using a declaration as a condition, it doesn't produce the warning, but the readability still seems to suffer.

Community
  • 1
  • 1
sje397
  • 41,293
  • 8
  • 87
  • 103

2 Answers2

5

It's because of the C++ standard, 6.4 p1.

Selection statements choose one of several flows of control.

selection-statement:

if ( condition ) statement
if ( condition ) statement else statement
switch ( condition ) statement

condition:

expression
type-specifier-seq declarator = assignment-expression
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
Abyx
  • 12,345
  • 5
  • 44
  • 76
  • I have added the start of the quote from the standard. The extra bit that is missing is that in the definition of `condition` it allows for extra parenthesis, but not definition of variables. – David Rodríguez - dribeas Dec 13 '10 at 10:05
3

This is not an assignment. It's a declaration. You can put declarations elsewhere as conditions, as in the following

if(int i = value) ...;
for(...; int i = value; ...) ...;
switch(int i = value) ...;
while(int i = value) ...;

This is a rarely used form, but it isn't an expression specified there. What you have done there is declaring a variable i which you can use in the body

// fire if get() returns non-null
if(weapon *w = get()) {
  w->fire();
}

And parentheses aren't allowed around such a declaration. I think that would make no sense.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • And I should add, don't do this EVER. Just because it's syntactically correct doesn't mean your fellow programmers will like you because of it. – Neil Dec 13 '10 at 09:15
  • @Neil - See the link in my comment under the question for a possible reason. – sje397 Dec 13 '10 at 09:17
  • No doubt a reasons exists as demonstrated by your link. Though there are clearer ways to do the same thing, so why sacrifice simplicity? – Neil Dec 13 '10 at 09:30
  • @Neil because it allows for user defined switch macros: http://bloglitb.blogspot.com/2010/11/fun-with-switch-statements.html – Johannes Schaub - litb Dec 13 '10 at 09:37
  • For another example, it can be used to inject variables into a block of code. Look the implementation of `BOOST_FOREACH` (if you dare :P, well, the idea is not that hard, metaprogramming to get the correct types is what makes the macro harder to read) – David Rodríguez - dribeas Dec 13 '10 at 09:58
  • @Johannes - I edited the title somewhat to take into account your first two sentences. – sje397 Dec 13 '10 at 10:22