C++ colon syntax with function body - c++

I've encountered an example (for a trivial function-try-block), from which seems to utilize one of the more obscure of aspects of C++ syntax to which (like most obscure aspects of the language) I can not seem to find documentation for.
I've searched the Google to no avail, with all searches returning (rather uselessly) only for constructor initialization (which I'm familiar with), but what I would like to know is the importance of the body: and handler: statements in this constructor block:
class foo{
foo() try
//initalizer list that could throw
{
body:
//do stuff that could possibly throw
} catch(std::exception &e) {
handler:
throw;
}
};
The original author abruptly adds this syntax in a single example and I would like to know the implications of such linguistic constructs

The XXX: is a label. It doesn't serve any functional purpose in the code you posted. It may have been put in by the author to help them organize the code.
You can use labels with goto statements, as in goto XXX; to jump to that point in your code, although I'll leave it up to you to decide if that is a good think or now.

foo::foo()
try
{
body:
//... do stuff that could possibly throw
}
catch(std::exception &e){
handler:
throw;
}
That piece of code has two rather unusual constructs. The first is what you already pointed out and has already been explained in mjk's answer: body and handler are labels. Labels are used for gotos, and that in turn can be used for flow control (determining where the code should continue executing). Now, gotos should rarely be used, as there are very few cases where they cannot be substituted by other flow controls (if,for,while,do...) that would make it more readable. Since gotos are rarely used, labels are also rarely used.
The second interesting construct is the function-level try block:
foo::foo()
try {
} catch (std::exception const &) {
}
Note that there try catch is not inside the constructor body, but actually outside the {}. This is also a rare construct. It was designed to support catching an exception during the evaluation of the initializer list in the constructor (which in the code above is implicit). If the type has a base, or members whose constructors could throw, the constructor's body would never be evaluated and a regular try-catch would not be useful to treat that exception. The function level try block encloses also the initializer list and will catch any exception thrown during the evaluation of the different submember's constructors. It is a rarely used construct since you cannot really do much in the catch block. The exact state of what has been or has not been constructed is unknown and cannot be verified so the only possible use is to rethrow either the same exception or a different one. The syntax in a more complete example would be:
T::T()
try
: base1(args), base2(), member1(), member2() //...
{
// body
} catch (exception1 const& ex1) {
// ...
throw; // rethrow same exception
} catch (exception2 const& ex2) {
// ...
throw different_exception();
}

Related

try-catch without argument, use reference?

As mentioned in many previous answers, one should throw exceptions by value and catch them by reference ([A], [B]), such as
try {
// throw std::exception();
}
catch(std::exception &e) {
// handle exception
}
If you aren't going to make use of the exception itself (even though you should), this will however generate annoying "unused variable" warnings on compile. To avoid these, you can omit the parameter (e in the example above), at which point the catch block will trigger for the defined exception, but you won't have a variable to bother with.
However, almost every time I see this variable-less catch block, it is not declared by reference, but by value, as in
try {
// throw std::exception();
}
catch(std::exception) {
// handle exception
}
Even Our Lord and Savior has posted an answer this way (as have others). I did find one instance where references are used, though.
Since the variable isn't used, slicing isn't a problem, so there should be no effective difference between catching by value or by reference. However, why do people seemingly make a distinction between the with-variable and without-variable cases? Saving themselves the effort of adding that ampersand?
And, micro-optimizing as it may be (especially given how exceptional exceptions should be), doesn't the by-value case incur a casting cost (to see if the catch is appropriate for the thrown exception) mitigated when done by-reference?
Since the variable isn't used, slicing isn't a problem.
But you'd be forcing a copy in the case of a slice. Not that this is particularly problematic, since the exception ought to be on the rarely-taken code path.
However, if you were to re-throw the exception as a nested exception after a copy/slice then the final result might be surprising. e.g.:
struct E : std::runtime_error { using std::runtime_error::runtime_error; };
throw E("");
...
catch(std::runtime_error)
{
std::throw_with_nested(std::logic_error(""));
}
... further down the call stack...
catch(std::exception& e)
{
// what did we actually catch? std::runtime error nested in a std::logic_error, or
// E nested in a std::logic_error?
}

Using RAII to nest exceptions

So the way to nest exceptions in C++ using std::nested_exception is:
void foo() {
try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
}
But this technique uses explicit try/catch blocks at every level where one wishes to nest exceptions, which is ugly to say the least.
RAII, which Jon Kalb expands as "responsibility acquisition is initialization", is a much cleaner way to deal with exceptions instead of using explicit try/catch blocks. With RAII, explicit try/catch blocks are largely only used to ultimately handle an exception, e.g. in order to display an error message to the user.
Looking at the above code, it seems to me that entering foo() can be viewed as entailing a responsibility to report any exceptions as std::runtime_error("foo failed") and nest the details inside a nested_exception. If we can use RAII to acquire this responsibility the code looks much cleaner:
void foo() {
Throw_with_nested on_error("foo failed");
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
Is there any way to use RAII syntax here to replace explicit try/catch blocks?
To do this we need a type that, when its destructor is called, checks to see if the destructor call is due to an exception, nests that exception if so, and throws the new, nested exception so that unwinding continues normally. That might look like:
struct Throw_with_nested {
const char *msg;
Throw_with_nested(const char *error_message) : msg(error_message) {}
~Throw_with_nested() {
if (std::uncaught_exception()) {
std::throw_with_nested(std::runtime_error(msg));
}
}
};
However std::throw_with_nested() requires a 'currently handled exception' to be active, which means it doesn't work except inside the context of a catch block. So we'd need something like:
~Throw_with_nested() {
if (std::uncaught_exception()) {
try {
rethrow_uncaught_exception();
}
catch(...) {
std::throw_with_nested(std::runtime_error(msg));
}
}
}
Unfortunately as far as I'm aware, there's nothing like rethrow_uncaught_excpetion() defined in C++.
In the absence of a method to catch (and consume) the uncaught exception in the destructor, there is no way to rethrow an exception, nested or not, in the context of the destructor without std::terminate being called (when the exception is thrown in the context of exception handling).
std::current_exception (combined with std::rethrow_exception) will only return a pointer to a currently handled exception. This precludes its use from this scenario as the exception in this case is explicitly unhandled.
Given the above, the only answer to give is from an aesthetic perspective. Function level try blocks make this look slightly less ugly. (adjust for your style preference):
void foo() try {
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
}
catch(...) {
std::throw_with_nested(std::runtime_error("foo failed"));
}
It's impossible with RAII
Considering the simple rule
Destructors must never throw.
it is impossible with RAII to implement the thing you want. The rule has one simple reason: If a destructor throws an exception during stack unwinding due to an exception in flight, then terminate() is called and your application will be dead.
An alternative
In C++11 you can work with lambdas which can make life a little easier. You can write
void foo()
{
giveErrorContextOnFailure( "foo failed", [&]
{
// code that might throw
std::ifstream file("nonexistent.file");
file.exceptions(std::ios_base::failbit);
} );
}
if you implement the function giveErrorContextOnFailure in the following way:
template <typename F>
auto giveErrorContextOnFailure( const char * msg, F && f ) -> decltype(f())
{
try { return f(); }
catch { std::throw_with_nested(std::runtime_error(msg)); }
}
This has several advantages:
You encapsulate how the error is nested.
Changing the way errors are nested can be changed for the whole program, if this technique is followed strictly program wide.
The error message can be written before the code just as in RAII. This technique can be used for nested scopes as well.
There's less code repetition: You don't have to write try, catch, std::throw_with_nested and std::runtime_error. This makes your code more easily maintainable. If you want to change the behavior of your program you need to change your code in one place only.
The return type will be deduced automatically. So if your function foo() should return something, then you just add return before giveErrorContextOnFailure in your function foo().
In release mode there will typically be no performance panelty compared to the try-catch-way of doing things, since templates are inlined by default.
One more interesting rule to follow:
Do not use std::uncaught_exception().
There's a nice article about this topic by Herb Sutter which explains this rule perfectly. In short: If you have a function f() which is called from within a destructor during stack unwinding looking like this
void f()
{
RAII r;
bla();
}
where the destructor of RAII looks like
RAII::~RAII()
{
if ( std::uncaught_exception() )
{
// ...
}
else
{
// ...
}
}
then the first branch in the destructor will always be taken, since in the outer destructor during stack unwinding std::uncaught_exception() will always return true, even inside functions called from that destructor including the destructor of RAII.

Not All Control Paths Return a Value? Warning

Ive got a short bit of code that is giving me the following the warning upon compilation:
'BGOLUB::Containers::Stack::Pop' : not all control paths return a value
Here is the code:
template<typename T>
T Stack<T>::Pop()
{
try
{
if (m_index<0) throw OutOfBoundsException(m_index);
--m_index;
return(m_array[m_index]);
}
catch(OutOfBoundsException&)
{
cerr<<"Underflow Index = "<<m_index<<endl;
}
catch(...)
{
cerr<<"Unhandled Error Occured"<<endl;
}
}
Any advice?
Many thanks!
Any advice?
The compiler is giving you the best advice. Not all the control paths in your function contain a return statement, and your function is supposed to return a value.
If an exception is thrown and control is transferred to a catch handler, that handler will print something to cerr and then flow off the end of your function without actually returning anything.
This is Undefined Behavior. Per Paragraph 6.6.3/2 of the C++11 Standard:
[..] Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
For default-constructible values, you could fix this by adding a return T() statement right before the end of your function:
template<typename T>
T Stack<T>::Pop()
{
try
{
// ...
}
catch (OutOfBoundsException&)
{
// ...
}
catch (...)
{
// ...
}
return T();
// ^^^^^^^^^^^
}
A more reasonable approach is, however, to not have Pop() swallow the exception, but rather re-throw it. Pop() does not have strategic-level information on how to recover from an error occurred in this context:
template<typename T>
T Stack<T>::Pop()
{
try
{
// ...
}
catch (OutOfBoundsException&)
{
// ...
throw; // <== Re-throw after printing the diagnostic
}
catch (...)
{
// ...
throw; // <== Re-throw after printing the diagnostic
}
}
Even better would be if the responsibility for logging an error message did not belong to Pop() at all, since Pop() is likely supposed to be re-used by code with different requirements in this sense (some may not want to log anything, some may want to log messages to a file, some may want to log messages in a different language, and so on).
So a more reasonable version of your function would actually be:
template<typename T>
T Stack<T>::Pop()
{
if (m_index<0) throw OutOfBoundsException(m_index);
--m_index;
return(m_array[m_index]);
}
In general, you should try (no pun intended) to avoid try/catch blocks unless you have to:
Translate an exception
Recover from the error (but you need strategic knowledge for doing this)
If this not your task (as is the case for a function like Pop() above), in most situations the best thing to do is to not handle exceptions at all and let them propagate up the call stack.
To quote Dave Abrahams:
Often the best way to deal with exceptions is to not handle them at all. If you can let them pass through your code and allow destructors to handle cleanup, your code will be cleaner.
To avoid leaking memory, resources, or in general responsibilities, write code that is exception-safe by using adequate RAII wrappers. Excellent guidelines in this sense are given in this two-part talk by Jon Kalb.
In particular, avoid writing catch (...) handlers: exceptions were invented to prevent programmers from ignoring errors, and swallowing them all in a universal handler without re-throwing them is the best way to ignore them.
NOTE:
Notice, that your implementation of Pop() is a bit problematic: what happens if the copy constructor or move constructor of T throws when returning the element back to the caller, after you already modified the stack pointer?
This is the reason why the C++ Standard Library defines two separate functions pop() and top(): because it allows to offer strong guarantee, i.e. to give transactional semantics to your pop() operation - either the element is removed without exceptions being thrown, or the function had no effect at all.
You need either rethrow exceptions, or return something probably T() at the end of function.
When the exception is thrown, it will be caught by one of the two catch statements. However, they still need to return a value from the function. You could place a return statement right at the end of your function.
However, if Pop throws an exception because the Stack is empty, it makes much more sense for it to let the exception propagate out of the function. Why is Pop itself attempting to handle the exceptional situation?
I would recommend using brackets with all of your if statements, even with one-line bodies. They are not strictly necessary, and you can write perfectly legal code without them, but they make your code much more readable, and errors such as this will be much easier to find.
Additionally, it seems you have a fundamental misunderstanding of how exceptions work. If your code were to encounter an exception, it would jump straight to the catch block, and not execute any subsequent code in the try block. Therefore, the return statement in you try block will never be reached, and your function will not return anything, since the catch blocks lack return statements.
You can resolve this issue by adding a return statement in your catch block.

Function try blocks, but not in constructors

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 ?
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.
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.
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.
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)
A function-try-block is equivalent to a try block inside the function spanning the whole function unless you have a constructor or destructor.
On a constructor, the function-try-block also catches exceptions thrown by constructors of your base classes and non-static data members. Catching those is not possible with a regular try block spanning the statement-block of the constructor. This is the primary use-case for function-try-block.
On a destructor, the function-try-block also catches exceptions thrown by destructors of base classes and your non-static data members. This cannot be achieved using a try block inside the destructor. Note that destructors that throw are bad design, nonetheless they are legal in C++ and this is the way to deal with them.
In both these cases, additional rules apply: You cannot use return in the function-try-block’s catch clauses of a constructor because a data member may not be properly constructed; however, you may use throw and at the end of every catch, there is an implicit throw; statement. In a destructor’s function-try-block, at the end of every catch, there is also an implicit throw;, but an explicit return; is allowed.

Can you really have a function/method without a body but just a try/catch block?

Note that this function does not have a "{" and "}" body. Just a try/catch block:
void func( void )
try
{
...
}
catch(...)
{
...
}
Is this intentionally part of C++, or is this a g++ extension?
Is there any purpose to this other than bypass 1 level of {}?
I'd never heard of this until I ran into http://stupefydeveloper.blogspot.com/2008/10/c-function-try-catch-block.html
Yes, that is valid C++. One purpose i've found for it is to translate exceptions into return values, and have the code translating the exceptions in return values separate from the other code in the function. Yes, you can return x; from a catch block like the one you showed (i've only recently discovered that, actually). But i would probably just use another level of braces and put the try/catch inside the function in that case. It will be more familiar to most C++ programmers.
Another purpose is to catch exceptions thrown by an constructor initializer list, which uses a similar syntax:
struct f {
g member;
f() try {
// empty
} catch(...) {
std::cerr << "thrown from constructor of g";
}
};
Yes, it is standard. Function try blocks, as they're called, aren't that much use for regular functions, but for constructors, they allow you to catch exceptions thrown in the initialiser list.
Note that, in the constructor case, the exception will always be rethrown at the end of any catch blocks.