9

just a quick question. Is there any difference between

void f(Foo x) try
{
   ...
}
catch(exception& e)
{
   ...
}

and

void f(Foo x)
{
    try { ... }
    catch (exception& e)
    {
        ...
    }
}

?

If no, why are function try blocks for (the case of initialization lists for constructors being put aside) ? What happens if the copy constructor of Foo throws an exception when x is passed to f ?

Alexandre C.
  • 53,934
  • 10
  • 121
  • 192

4 Answers4

10

Function try blocks are only ever needed in constructors. In all other cases exactly the same effect can be achieved by enclosing the entire body of the function in a normal try/catch block.

If the copy constructor used to initialize a parameter throws an exception this happens before the function call. It cannot be caught by a function try block or exceptional handler in the function as the function doesn't get called.

CB Bailey
  • 700,257
  • 99
  • 619
  • 646
  • 5
    Which means that function try blocks for non-constructor functions are JUST an alternative syntax, no semantic purposes, which may indeed be an arguable argument for their existence. On the other hand, there are far too many inexplicable things in C++, even among those which have nothing to do with compatibility. – Armen Tsirunyan Oct 08 '10 at 11:09
6

Some things are allowed because it would be harder to disallow them. Allowing function try blocks on some, but not all function bodies would make the grammar and compilers more complicated.

MSalters
  • 167,472
  • 9
  • 150
  • 334
3

Just spotted an interesting point in this Dr. Dobb's article (although quite old):

...remember that you can't return a value inside a function-try-block handler. So it makes no sense to use a function try block for a non-void function

and this is their code example:

int f()
try
{
   ...
}
catch(Error &e)
{
   // oops, can't return int from here!
}

Which actually means that function try blocks are weaker than "regular" try blocks and their use should be discouraged other than in constructors.

(the article is from 2000, so it'd be nice if someone would comment on whether this is still so in the current standard)

davka
  • 13,226
  • 11
  • 58
  • 82
  • 1
    ...unless the "catch" block itself unconditionally throws or re-throws, in which case the function try block is the cleanest way to write this, IMO. – Nemo Mar 16 '16 at 00:24
  • 2
    (Comment is added 5 years later:) I tested with gcc 5.4 -- There, I can return a value from the catch-block. However, I did not study any standards. – ralfg Aug 24 '16 at 07:40
  • 1
    This answer is wrong and AFAIK was so already at the time of creation, see [here](http://en.cppreference.com/w/cpp/language/function-try-block), in particular the example at the bottom. – Walter Aug 24 '16 at 08:12
  • 2
    I tested if we can return from catch handler of a function try block on a non-void function; I was able to. But as per the cppreference entry this is undefined behavior. – anurag-jain Jul 03 '17 at 08:25
1

Function try blocks were added expressly for the purpose of catching exceptions in constructor initialization lists.

In your example there are no constructor initializations, so there is no difference between the two forms.

Ferruccio
  • 96,346
  • 38
  • 221
  • 297
  • which doesn't solve the problem of static/global objects of potentially-throwing-in-constructor classes, because the exception is rethrown anyway. – Armen Tsirunyan Oct 08 '10 at 11:11
  • 3
    @Armen: Constructors _have_ to throw if the object cannot be initialized. This is the _only_ way to report construction failure. – Alexandre C. Oct 08 '10 at 11:15