Reputation: 5552
This is kind of a follow up on Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?
I would like to detect if someone is creating MyClass
in the destructor of another class (or with an active destructor somewhere in the call stack).
class MyClass
{
public:
MyClass(){
assert(???what to put here????);
}
}
void f(){
MyClass m; //whether this asserts should be context dependant
}
class OtherClass{
~OtherClass(){
MyClass m; //this should assert
f(); //this should too;
}
}
int main()
{
MyClass m; //this should not assert
f(); //this should also not assert
}
One attempt might be:
assert(!std::uncaught_exception());
but that would only work if the destructor is being invoked because of an exception, not if it is invoked because the object went out of scope.
Upvotes: 11
Views: 322
Reputation: 618
you cannot detect this and you don't want to. it's not your class's business. if someone will call you from noexcept destructor, he will catch exceptions
Upvotes: 1
Reputation: 145359
You can't detect how your function is called unless you make the callers supply that information.
Also, as I recall Visual C++ never implemented std::uncaught_exception
, so that would be ungood (for portable code) even where it was known that no destructor invoked any try
block.
However, it's trivial to detect whether a scope is exited due to an exception or not.
Simply put that scope in a try
-block; that's what it's for.
For example,
class Transaction
{
private:
bool failed_;
Transaction( Transaction const& ); // deleted
Transaction& operator=( Transaction const& ); // deleted
public:
void fail() { failed_ = true; }
void commit() { ... }
// More functionality, then
~Transaction()
{
if( failed_ ) { rollback(); }
}
Transaction(): failed_( false ) {}
};
void foo()
{
Transaction transaction;
try
{
// blah blah
}
catch( ... )
{
transaction.fail();
throw;
}
}
Disclaimer: I haven't used that pattern so can't attest to how practical it is.
Upvotes: 0