Re: Defeating (N)RVO
Thomas Maeder ha scritto:
"peter koch larsen" <peter.koch.larsen@gmail.com> writes:
I am thinking about "renewing" an old system which did not use
exception and begin using exceptions. For that purpose I need to be
able to convert our current errorcodes to exceptions by throwing an
exception in the destructor (if the errorcode is not destroyed during
exception unwinding) in exactly those cases where the errorcode has not
been "inspected" by the program. The problem comes in situations such
as this one:
Side note: throwing destructors are very often a bad idea.
Agreed. The OP's design is dubious to say the least.
The problem is that if NRVO is in place and somefunc() failed the
check in inner will mark the errorcode examined which it isnt
really.
If the (non)invokation of the copy-constructor matters here, then I
agree with the other posters that it is badly written. IMHO
In fact I think that the OP's code works *only* when (N)RVO occurs, and
does *not* work otherwise. That's because if the optimization does not
occur then somefunc() may throw even before giving the caller the chance
to inspect the error code, because there is a temporary of type
ErrorCode that gets destroyed before somefunc() returns.
One solution I see is to rely on the "destructive copy" behavior of
std::auto_ptr, for example:
class ErrorCode
{
std::auto_ptr<ErrorInfo> error;
public:
ErrorCode() {} // success code
ErrorCode(/*...*/) : error(new ErrorInfo(/*...*/)) {}
// notice: implicit copy ctor will copy the auto_ptr
// with destructive copy semantic
~ErrorCode()
{
if(error.get() && !uncaught_exception())
throw whatever(*error);
}
bool ok()
{
if(error.get())
{
error.reset(); // discard error: it has been inspected
return false;
}
else
return true;
}
// even better:
std::auto_ptr<ErrorInfo> get_error()
{
return error; // will reset error automatically
}
};
A plus of using std::auto_ptr is that you can nicely pack your error
info into a class.
HTH,
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]