Есть ли хитрость, чтобы обнаружить, если объект создается во время выполнения другого деструктора?

Это своего рода продолжение Почему Александреску не может использовать std :: uncaught_exception () для реализации SCOPE_FAIL в ScopeGuard11?

Я хотел бы обнаружить, если кто-то создает MyClass в деструкторе другого класса (или с активным деструктором где-то в стеке вызовов).

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
}

Одна попытка может быть:

assert(!std::uncaught_exception());

но это будет работать только в том случае, если деструктор вызывается из-за исключения, а не в том случае, если он вызывается из-за того, что объект вышел из области видимости.

11

Решение

Вы не можете обнаружить это, и вы не хотите. это не бизнес вашего класса. если кто-то позвонит вам из деструктора noexcept, он поймает исключения

1

Другие решения

Вы не сможете определить, как вызывается ваша функция, если вы не заставите звонящих предоставить эту информацию.

Кроме того, насколько я помню, Visual C ++ никогда не реализовывался std::uncaught_exception, так что это было бы плохо (для переносимого кода), даже если было известно, что никакой деструктор не вызывал try блок.

Тем не менее, тривиально определить, вышла ли область из-за исключения или нет.

Просто поместите эту область в try-блок; вот для чего это.

Например,

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;
}
}

Отказ от ответственности: я не использовал этот шаблон, поэтому не могу подтвердить, насколько это практично.

0

По вопросам рекламы [email protected]