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'.