Why do try..catch blocks require parentheses?

In other operations, such as if ... else, you can avoid bindings, if there is only one command in a block, you cannot do this with try ... catch blocks: the compiler does not buy it. For example:

try do_something_risky(); catch (...) std::cerr << "Blast!" << std::endl; 

With the above code, g ++ just says that it expects '{' before do_something_risky (). Why is this difference in behavior between try ... catch and, say, if ... else?

Thank!

+38
c ++ syntax try-catch
Jun 09 '10 at 18:57
source share
9 answers

Straight from the C ++ spec:

 try-block: try compound-statement handler-seq 

As you can see, all try-block expect a compound-statement . By definition, a compound statement is a set of statements enclosed in braces.

All that is contained in the composite statement provides the creation of a new scope for the try block. It also makes everything a little easier to read in my opinion.

You can check this on page 359 C ++ Language Specification

+15
Jun 09 '10 at 19:09
source share

I don’t know why, but one advantage is that the problem of accusation does not exist. See dangling-else for the ambiguity that can occur when braces are optional.

+11
Jun 09 '10 at 7:01
source share

Read this link . The main reason is to manage the area and distribution of objects that need to be created and destroyed in case of real exceptions.

So, I think the authors of the C ++ grammar are asking the authors of g ++ (or any standards that comply with the C ++ compiler) to prepare it for the worst possible cases, and the g ++ authors seem to have done it.

+7
Jun 09 '10 at 19:26
source share

Well, firstly, how grammar works.

Secondly, I believe that the goal is to force create a new scope for exception blocks (correct me if I am wrong).

+5
Jun 09 '10 at 19:00
source share

Why? The tradeoff between security and backward compatibility.

Lessons learned from if ... else have shown that the required braces eliminate errors. Now, C ++ ISO people have a strong preference for backward compatibility with C, so they did not change the C syntax for if ... else. But new designs require brackets to demarcate the controlled blocks, since they will not be displayed in the old C code, and therefore backward compatibility is not a problem.

+4
Jun 10 '10 at 9:27 a.m.
source share

This is how they wanted to be. There is no excuse, this is the law.

+2
Jun 09 '10 at 19:02
source share

The syntax of the try block is:

 try compound-statement handler-sequence 

where the handler sequence is a sequence of one or more handlers that have the following syntax:

 catch (type-specifier-seq declarator) compound-statement catch (...) compound-statement 

This is different from other statements such as control instructions (if, while, for, etc.). The syntax for them is:

 if (condition) statement-true else statement-false while (condition) statement for (init-statement; condition; iteration_expression) statement etc. 

Now the question is, why is a compound statement needed in a try block instead of a single statement?

Think about this code:

 int main() { // before try-statement. try g(); catch (std::runtime_error e) handleError(e); // after try-statement. } 

I know that catching by value is bad practice (for example, possible slicing of objects, etc.), but I did this to prevent discussion of the duration of the exception storage and to simplify the reasoning.

Now think about the duration of storage and the connection "e". What you expect is that "e" can only be passed before the handleError function is called, but not after the call is completed. It should have an automatic storage duration and lack of communication in this "area". This could probably be done by implicitly defining the local scope, as in other operators, but making the declaration of presentation look like a function parameter was probably the best idea. Therefore, a block (compound operator) is needed. Se bellow.

Now think about trying and making a statement after that. There is no reason to use the try there keyword, and there is no reason to use the compound statement, but the syntax can become ambiguous and complex.

Here is what Straustrup said about this in Exception Handling for C ++ :

 It might be possible to simplify the try { ... } catch (abc) { ... } syntax by removing the apparently redundant try keyword, removing the redundant parentheses, and by allowing a handler to be attached to any statement and not just to a block. For example, one might allow: void f() { g(); catch (x1) { /* ... */ } } as an alternative to - 28 - void f() { try { g(); } catch (x1) { /* ... */ } } The added notational convenience seems insignificant and may not even be convenient. People seem to prefer syntactic constructs that start with a prefix that alerts them to what is going on, and it may be easier to generate good code when the try keyword is required. 

And after a more detailed explanation:

 Allowing exception handlers to be attached to blocks only and not to simple statements simplifies syntax analysis (both for humans and computers) where several exceptions are caught and where nested exception handlers are considered (see Appendix E). For example, assuming that we allowed handlers to be attached to any statement we could write: try try f(); catch (x) { ... } catch (y) { ... } catch (z) { ... } The could be interpreted be in at least three ways: try { try f(); catch (x) { ... } } catch (y) { ... } catch (z) { ... } try { try f(); catch (x) { ... } catch (y) { ... } } catch (z) { ... } try { try f(); catch (x) { ... } catch (y) { ... } catch (z) { ... } } There seems to be no reason to allow these ambiguities even if there is a trivial and systematic way for a parser to chose one interpretation over another. Consequently, a { is required after a try and a matching } before the first of the associated sequence of catch clauses. 

As Straustrup said, without curly braces, a statement can mean different things depending on the rule, and you may have to put curly braces to clarify the intention. Can we make some that look complicated with an if statement, like in the Stroustrup example? Of course we can, something like this, for example:

 if (c1) if (c2) f(); else if (c3) g(); else h(); 

This is actually equivalent to:

 if (c1) { if (c2) f(); else { if (c3) g(); else h(); } } 

But I think this is less problematic than the try-block case. There are two syntaxes for if-statament:

 if (condition) statement-true if (condition) statement-true else statement-false 

because it makes sense not to sometimes perform any action. But this does not make sense in try-block without catch-clause. "Try" can be omitted, but not practical, as Straustrup said, but the catch clause cannot, if you specify a try block. In addition, there may be more than one catch associated with the same try block, but only one is executed based on rules that depend on the type of exception and the order of catch-clauses.

Now, if the if-else syntax changes to:

 if (condition) compound-statement-true else compound-statement-false 

then you should write if-else as follows:

 if (c1) { f(); } else { if (c2) { g(); } else { h(); } } 

See that the keyword 'elseif' is missing; there is no special syntax for 'else if'. I think that even the “put brackets always” advocates do not like to write like this: instead, write:

 if (c1) { f(); } else if (c2) { g(); } else { h(); } 

I think that this is not a strong reason for defining the syntax, as indicated above, and introducing the keyword 'elseif' into the language or defining a special syntax for 'else if'.

+2
Oct 13 '16 at 3:50
source share

Not sure if you are using .NET, but the CLR uses curly braces as flags.

http://dotnet.sys-con.com/node/44398

From the article: “The SEH table (structure exception handling) consists of a set of sentences describing the structure of the protected code. The table has a set of binary flags describing the type of exception handling sentences: the Try Offset flag, which is the beginning of the protected code block; the Try Length flag, which is the length of the protected code; Flags of the Offset and Handler Length handler, which describe in detail the beginning of the exception handler block and its length, as well as the Token or Filter Offset flag, depending on the type of exception handler that has been defined. This information allows the CLR to determine what to do when an exception occurs, it displays the beginning of the protected code block, the code to execute for the exception, and special semantics related to filtering or other special circumstances.

I would suggest that other frameworks do the same.

+1
Jun 09 '10 at 19:11
source share

This is mainly because

 if (a) int b = 10; else int b = 5; b += 5; 

Error because if ... else without {} is the syntax shortcut for this

 if (a) { int b = 10; } else { int b = 5; } b += 5; 

which explicitly tells you that int b is in a different scope than the rest of the software.

If I am not mistaken, the following also fails

 a ? int b = 10 : int b = 5; b += 5; 

Of course, your compiler can optimize this code for you ... but it should technically crash due to areas in the if / else statement.

Whenever you see {} , you define the scope of the software.

-Stephen

0
Jun 09 2018-10-10T00:
source share



All Articles