Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No curly braces around main() -- why does this work?

I'm working through a book on C++ and in the chapter on errors it has this program (I left a couple of minor things out but it's mostly this):

int main()
try { 
        // our program (<- this comment is literally from the book)
        return 0;
}
catch(exception& e) {
    cerr << "error: " << e.what() << '\n';
    return 1;
}
catch(...) {
    cerr << "Unknown exception\n";
    return 2;
}

This compiled but of course it did nothing so I'm still wondering about

  1. why there isn't a set of curly braces enclosing everything after main()? Are the blocks or shall I call them "catchphrases" (ha!) part of main() or not?
  2. If they are functions how come there's no "int" before catch(whatever)?
  3. If they're not functions, what are they?
  4. re catch(...), I've never seen ellipses used that way. Can I use ellipses anywhere to mean "anything"?
like image 943
punstress Avatar asked Aug 03 '12 18:08

punstress


People also ask

Why does Python not use curly braces?

Those that get used to the Python way of doing things tend to start seeing curly braces as unnecessary line noise that clutters code. On the other hand, 'the whitespace thing' is possibly the single biggest reason why some developers refuse to even try Python.

What happens in a IF statement where there is no curly braces?

One-line statement Well if there is only one statement to execute after if condition then using curly braces or not doesn't make it different. Without curly braces only first statement consider in scope so statement after if condition will get executed even if there is no curly braces.

Why we use curly parenthesis not any other brackets?

Curly braces indicates the block of statements in C programming language. The function in C has braces in its syntax. But one can put braces where logically related statements are written. A single statement in loop or if-else block need not be written within braces.

Does every loop require curly braces?

If the number of statements following the for/if is single you don't have to use curly braces. But if the number of statements is more than one, then you need to use curly braces.


5 Answers

If you use a try block directly instead of braces, the try block catches everything that happens in the function. This is useful in constructors so you can catch exceptions in the initialization list.

This will catch exceptions from bar's constructor:

void Foo::Foo() try : bar() {
    // do something
} catch(...) {
    // do something
}

This will only catch exceptions in the body:

void Foo::Foo() : bar() {
    try {
        // do something
    } catch(...) {
        // do something
    }
}
like image 79
Dirk Holsopple Avatar answered Oct 04 '22 09:10

Dirk Holsopple


1 why there isn't a set of curly braces enclosing everything after main()? ...

There is, it just has the keyword try before the opening brace, and some catch blocks after the end of main.

... Are the blocks or shall I call them "catchphrases" (ha!) part of main() or not?

2 If they are functions how come there's no "int" before catch(whatever)?

3 If they're not functions, what are they?

They're keywords, not functions, and they're part of main, despite the try coming between the int main() definition and its {} body. See the motivating case below for another example.

4 re catch(...), I've never seen ellipses used that way. Can I use ellipses anywhere to mean "anything"?

there are a couple of overloaded meanings of ellipsis in C++.

  • catch(...) means catch anything, it's like a wildcard for the exception type (and should be the last catch if you have several)
  • int printf(char *, ...) means a function takes a variable argument list, which entirely disables type-checking of arguments and is easy to get wrong (but occasionally useful)
  • template <typename... TypePack> means a template accepts a variable type list, which is very useful for metaprogramming but completely out of scope here
  • #define DEBUG(str, ...) is a variadic macro, analogous to the variable-argument function

Function-level try/catch blocks are a way of wrapping the whole function body in an exception handler. So, here, the main function block is inside the try { ... }.

IIRC this was introduced specifically to allow constructors to wrap their initializer lists with a try/catch, to handle exceptions thrown from subobject constructors.

Eg. (motivating case)

C::C() try : Base(1), member(2)
{ ...
}
catch (...) {
    // handle Base::Base or member construction failure here
}

Note that there is no other way to catch exceptions thrown from base class or member subobject constructors, because they'll always do at least default construction before your constructor body starts, even if you omit the initializer list.

like image 21
Useless Avatar answered Oct 04 '22 08:10

Useless


That is a rarely used feature of the language. You can enclose a whole function in a try catch block:

void f()
try 
{         // function starts here
...
}         // function ends here
catch (...) 
{}

The feature is rarely used as it is almost never useful. In the case of a regular function, you can just have a try/catch block that covers all the code of the function, so in this case the feature would not be needed. It has limited functionality in constructors, as it allows catching exceptions on the initializer list, that cannot be enclosed in a try/catch block otherwise.

But the problem there is that there is very little that can be done in the catch block: construction failed so an exception must be thrown (the catch block can throw a different exception to what was caught, but it has to throw). At the same time, you cannot really perform any cleanup, since at the point where the exception is caught you might not know which of the elements in the initialization list threw, which means that you might not know (in the general case) which of the member objects have been constructed or not.

like image 32
David Rodríguez - dribeas Avatar answered Oct 04 '22 08:10

David Rodríguez - dribeas


It's function-try block. Yes, it's legal, but not needed in more cases. Look at this answer for explanations. What is the meaning of this syntax?

like image 41
ForEveR Avatar answered Oct 04 '22 09:10

ForEveR


Not sure about the missing curly braces around the main function, but it looks like others answered that all ready.

As for the rest of your question, try catch blocks are not functions outside the main, and do not need an int in front of them.

try {}: The program will try to run anything within this block, if it fails for whatever reason, it will be caught by the catch blocks.

catch (exception) {}: When an exception is thrown, it will be caught by a catch block with the specific Exception as its parameter, and allow for the programmer to handle that case.

catch (...) {}: Should catch anything that makes it through the first catch block..

like image 33
WebDevNewbie Avatar answered Oct 04 '22 10:10

WebDevNewbie