43

For example:

if (true) try
{
    // works as expected with both true and false, but is it legal?
}
catch (...)
{
    // ...
}

In other words, is it legal to put the try-block right after the if condition?

Davit Tevanian
  • 861
  • 8
  • 16
  • Yes [it's illegal]. The try block should be within the `if` statement. But why not just test the condition using try? – franklin Mar 14 '16 at 10:56
  • 58
    @franklin No, it is not illegal. – Columbo Mar 14 '16 at 11:01
  • 5
    Correct, it's not illegal. The brackets for the true-clause are optional in C and C++, and it's assumed whatever follows the if() is the true clause, and that a catch-clause that follows a try-clause is associated with that try-clause. Lots of companies' style guides will still gig you for not using the brackets, though. – Blair Houghton Mar 14 '16 at 16:45
  • 3
    `int main() try {} catch(...){}` is also legal. – nwp Mar 14 '16 at 23:55
  • @nwp: That is amazing! It looks like it's a new "feature" in C++0x. The motivation seems to be to allow constructor-initializers to be covered by the try/catch (e.g. `class foo { int bar; foo() try : bar(3) { ... } catch ...`). – ruakh Mar 15 '16 at 00:55
  • It's legal but should be indented, as both try and catch are subject to the if condition – edc65 Mar 15 '16 at 07:45
  • It's essentially an indentation issue. But perhaps the format is confusing because it bears syntactic similarities with [function-try-blocks](http://en.cppreference.com/w/cpp/language/function-try-block). – Leo Heinsaar Mar 15 '16 at 09:44
  • @ruakh: It's been present since the start. Not new in C++11. – Lightness Races in Orbit Jun 10 '16 at 13:27

4 Answers4

77

The syntax of a try block (which is a statement in C++) is

try compound-statement handler-sequence

And the syntax of if is:

attr(optional) if ( condition ) statement_true      
attr(optional) if ( condition ) statement_true else statement_false     

where:

statement-true - any statement (often a compound statement), which is executed if condition evaluates to true
statement-false - any statement (often a compound statement), which is executed if condition evaluates to false

So yes, your code is legal code in C++.

statement_true in your case is a try block.

In legality, it is similar to:

if (condition) for(...) {
    ...
}

But your code is not very readable and can be the victim of some C++ pitfalls when an else is added. So, it is advisable to add explicit {...} after if in your case.

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • I think that grammar is irrelevant to the code presented by OP, isn't it? – Angelus Mortis Mar 14 '16 at 11:03
  • 46
    @AngelusMortis If not grammar, what else would decide whether the piece of code is legal or not? – Mohit Jain Mar 14 '16 at 11:04
  • 6
    @AngelusMortis I was not trying to prove you are wrong. I put my point to discuss forward and understand your point of view about how could I make this answer more informative. – Mohit Jain Mar 14 '16 at 11:08
  • @AngelusMortis For example looking at [for loop syntax or grammar](http://en.cppreference.com/w/cpp/language/for) I can say `for(int i = 0; i < 15; ++i) {...}` is legal but `for(int i = 0; i < 20; i > 16; int j = 24) {...}` is not. – Mohit Jain Mar 14 '16 at 11:10
  • 9
    @MohitJain: Actually, the C++ language isn't fully specified by its grammar. E.g. `int x; int x;` is a simple example that's allowed by the grammar but illegal nonetheless. – MSalters Mar 14 '16 at 12:05
  • @MSalters Agreed. But I believe in this question concern of OP was to check whether the code is well-formed from syntax point of view. I mean syntax is one way to check whether the code is well formed. – Mohit Jain Mar 14 '16 at 12:06
  • 4
    Well, he asks whether it's legal, and that means it must be _permitted_ by the grammar, _and_ not banned by other rules. The grammar describes a superset of the valid C++ programs. But it's hard to prove a negative, of course. – MSalters Mar 14 '16 at 12:09
  • @MSalters You are right. The intent of the question is to ask whether the code snippet as it stands is well formed C++ code. – Mohit Jain Mar 14 '16 at 12:16
  • On the topic of brace-placement style: I wonder what the actual danger here is. I don't immediately see any at all. "if (c1) if (c2) s1; else s2;" can confuse some people, and can occasionally lead some people to attach an "else" to the wrong "if". But I don't see that danger with try-catch. – mjwach Mar 15 '16 at 17:46
  • @mjwach See http://stackoverflow.com/questions/359732/why-is-it-considered-a-bad-practice-to-omit-curly-braces?lq=1 – Barmar Mar 15 '16 at 18:37
  • @Barmar Nobody seems to advocate braces in try-catch there; it's mostly about if-else. But some people do point out the danger that in "if (c) s1; s2;" some careless maintainer will comment out the "s1" line and thus apply the "if" to s2, which could happen with braceless try-catch as well. I suppose that's a good enough answer to the question of what the danger might be (though by itself it doesn't strike me as justification for REQUIRING braces). – mjwach Mar 15 '16 at 19:02
  • @mjwach Actually, the more common problem with braceless if-else is adding a print statement while debugging. You're right that try-catch is different because the `catch` keyword makes that a syntax error. But once you get in the habit of putting braces around all blocks, I think it's best style to use them consistently everywhere. – Barmar Mar 16 '16 at 01:20
  • @LeoHeinsaar But language pitfalls are real – Mohit Jain Mar 16 '16 at 10:19
  • 1
    @MohitJain: I think your quote from the standard and then *your* claim that *"`statement_true` in your case is a `try` block"* lacks proof, because the quote does not say whether try-block is `statement_true` or not. All it says `if` block can be defined in terms of `statement_true`, but it does *not* define what `statement_true` is, does it? In that sense, your quote from the standard is meaningless and irrelevant to *your* claim because you did not *connect* all the mandatory text from the standard to back your claim. – Nawaz Dec 19 '16 at 04:16
  • Thanks @Nawaz for valuable input. You are right I assumed the meaning of text in syntax is clear and did not bother to explicitly add the details and left a gap in proof. – Mohit Jain Dec 19 '16 at 05:20
40

is it legal to put the try-block right after the if condition?

It is legal. Your code is same as (and better to write as):

if (true) {
    try
    {
        // works as expected with both true and false, but is it legal?
    }
    catch (...)
    {
        // ...
    }
}

So if the condition is false then the try-catch block won't be executed. If this is what you expect, it's fine.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 4
    If you remove the outermost `{` and `}` braces, the equivalence becomes trivially obvious. – Leo Heinsaar Mar 14 '16 at 14:33
  • 1
    I agree. It's just that removing the braces makes it obvious that the `if` statement in the original question is _exactly the same_ not counting spaces. Without braces, your formatting reveals that there's nothing "magical" in putting a _try-catch_ block right after the `if` statement. – Leo Heinsaar Mar 14 '16 at 15:02
  • 8
    As long as we're promoting good style, shouldn't the code stick to one or the other bracing style? Or is this meant to make everyone equally dissatisfied? ;) –  Mar 15 '16 at 01:19
  • Not sure I agree that this is better or more readable. This is more traditional, certainly, but ops way reads more like an english sentence, where as this reads like code. Apples and oranges maybe, but equally readable, and equally correct imho. This is like if blocks with a single, short statement. I'm for putting that statement on the same line and doing away with the braces. If it's all on the same line, you'd have to be blind not to realise you need to add braces if you want to add something to the block, and I believe most IDEs will insert the braces for you anyway (don't quote me though) – Kraiden Mar 15 '16 at 21:04
22

Yes. The braces of an if are optional. Imagine you have {} around the try { .. } catch { .. }.

It may interest you to know that this is what happens when you write if/else if/else; C++ doesn't actually have else if … so this:

if (A) {

}
else if (B) {

}

is actually parsed as this:

if (A) {

}
else
   if (B) {

   }

which is this:

if (A) {

}
else {
   if (B) {

   }
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
9

It's well-formed. try-blocks are statements as per [stmt.stmt]/1, and statements are following if (…) as per [stmt.select]/1.

Columbo
  • 60,038
  • 8
  • 155
  • 203