2013-02-18 12 views
11

Dies ist eine Art von Follow-up auf Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?Gibt es einen Trick, ob ein Objekt während der Ausführung eines anderen Destruktors erstellt wird?

Ich möchte jemanden erkennen, ob sich MyClass im Destruktor einer anderen Klasse (oder mit einem aktiven destructor irgendwo in den Call-Stack) zu schaffen.

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 
} 

Ein Versuch könnte sein:

assert(!std::uncaught_exception()); 

aber das würde nur funktionieren, wenn der destructor wegen einer Ausnahme aufgerufen wird, nicht, wenn es aufgerufen wird, weil das Objekt des Gültigkeitsbereich ging.

+7

Wenn du diese Destruktoren nicht explizit designierst, um ihre Ausführung irgendwie zu signalisieren, bezweifle ich, dass das möglich ist. Im Allgemeinen können Sie nicht sagen, woher Ihre Funktion aufgerufen wurde. –

+0

Wie tragbar soll die Lösung sein? – Flexo

+0

Sie können Ihre Lösung auf eine bestimmte Compiler-Version spezialisieren und den Stack im Konstruktor von 'MyClass' untersuchen, um den Destruktor von' OtherClass' zu finden. Ich persönlich denke, es ist viel zu viel Arbeit für das, was es ist ... und wird eine Fehlerquelle sein. – Synxis

Antwort

1

Sie können dies nicht erkennen und Sie möchten nicht. Es geht nicht um deine Klasse. Wenn dich jemand von noexcept destructor anruft, fängt er Ausnahmen

0

Sie können nicht feststellen, wie Ihre Funktion aufgerufen wird, es sei denn, Sie stellen die Informationen für die Anrufer bereit.

Auch, wie ich erinnere, Visual C++ nie implementiert std::uncaught_exception, so wäre das nicht gut (für tragbaren Code), auch wenn es bekannt war, dass kein Destruktor try Block aufgerufen.

Es ist jedoch trivial zu erkennen, ob ein Bereich aufgrund einer Ausnahme beendet wird oder nicht.

Setzen Sie diesen Bereich einfach in einen try-Block; Dafür ist es da.

Zum Beispiel

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

Haftungsausschluss: Ich habe nicht dieses Muster so kann nicht bezeugen, wie praktisch es ist verwendet.

Verwandte Themen