28

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"?
punstress
  • 1,177
  • 2
  • 14
  • 26
  • 2
    `catch (...)` is catch anything else, yes. As for them in general, look into exception handling in C++ (other languages have pretty similar syntax, too). – chris Aug 03 '12 at 18:30
  • And look here for a question about using function try blocks with `main`: http://stackoverflow.com/questions/8405390/function-try-catch-syntax-and-main – CB Bailey Aug 03 '12 at 18:32
  • Whoa, I came here about to write up "what crazy old compiler are you using that accepts that?" but then tested it in g++ 4.5.3, and was shocked to see it compile... – Adam Rosenfield Aug 03 '12 at 18:33
  • 2
    Oh right, function try blocks. I remember that from one of those *Crazy corners of C++* questions. – chris Aug 03 '12 at 18:33
  • 1
    http://stackoverflow.com/questions/11576275/what-is-the-meaning-of-this-syntax/11576306#11576306 –  Aug 03 '12 at 18:36
  • 1
    See http://www.drdobbs.com/introduction-to-function-try-blocks/184401297 for a more detailed explanation. – Adam Rosenfield Aug 03 '12 at 18:44
  • You only need the braces to group a set of statements. You've got only one statement, thus no braces required. – Hans Passant Aug 03 '12 at 19:44
  • Hans, I guess you're saying try { ... } is the one statement, no? Useless says the brackets after try are my main() brackets. I wonder if it's just 2 ways of seeing the same thing or is one correct? – punstress Aug 04 '12 at 21:27

6 Answers6

16

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
    }
}
Dirk Holsopple
  • 8,731
  • 1
  • 24
  • 37
  • 4
    Note that the use in constructors is limited. Before the end of the catch block, the constructor *must* throw (or retrow), and it is almost impossible to perform any short of cleanup in the general case. – David Rodríguez - dribeas Aug 03 '12 at 18:42
12

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.

Community
  • 1
  • 1
Useless
  • 64,155
  • 6
  • 88
  • 132
10

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.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

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?

Community
  • 1
  • 1
ForEveR
  • 55,233
  • 2
  • 119
  • 133
2

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

WebDevNewbie
  • 1,833
  • 1
  • 13
  • 17
0

1) That's a feature of C++, function try-catch block (see here, for example)
2) And yes, catch(...) { /* absolutely any exception gets caught here */ }

vines
  • 5,160
  • 1
  • 27
  • 49