Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw a temporary argument passed by reference

inline void my_assert( bool cond, const std::exception &e = my_assert_failed() ) 
{ 
    if ( !cond ) 
      throw e;
}

The standard ensures that:

A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.

And for a thrown temporary object:

The temporary persists as long as there is a handler being executed for that exception.

Can I infer that a temporary that is passed to my_assert survives until the catch block finishes?

like image 443
Michael Litvin Avatar asked Mar 05 '15 10:03

Michael Litvin


1 Answers

From N4296 (first draft after final C++14) [15.1p3]:

Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).

So you can't assume that your temporary "survives the throw". If throwing, the copy constructor of an exception object of type std::exception will be called with e as the argument. The temporary that e is bound to will be destroyed when control leaves the full expression containing the call to my_assert (either after a normal return or as part of stack unwinding, since you're conditionally throwing the exception).

There are circumstances when the copy construction of the exception object can be elided, but this is not one of them, according to [12.8p31.2]:

— in a throw-expression (5.17), when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

(emphasis mine)

like image 119
bogdan Avatar answered Oct 19 '22 21:10

bogdan