2013-02-18 13 views
11

Questa è una specie di follow-up su Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?C'è qualche trucco per rilevare se un oggetto viene creato durante l'esecuzione di un altro distruttore?

vorrei rilevare se qualcuno sta creando MyClass nel distruttore di un'altra classe (o con un distruttore attiva da qualche parte nello stack di chiamate).

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 
} 

Un tentativo potrebbe essere:

assert(!std::uncaught_exception()); 

ma che avrebbe funzionato solo se il distruttore viene richiamato a causa di un'eccezione, non se viene richiamato perché l'oggetto è andato fuori del campo di applicazione.

+7

A meno che non progettiate esplicitamente quei distruttori per segnalare comunque la loro esecuzione, dubito che ciò sia possibile. In generale, non puoi dire da dove è stata chiamata la tua funzione. –

+0

Quanto vuoi che sia portatile la soluzione? – Flexo

+0

È possibile specializzare la soluzione su una specifica versione del compilatore ed esaminare lo stack nel costruttore di 'MyClass', per trovare il distruttore di' OtherClass'. Personalmente penso che sia troppo lavoro per quello che è ... e sarà una fonte di errore. – Synxis

risposta

1

non è possibile rilevare questo e non si desidera. non sono affari della tua classe. se qualcuno ti chiamerà da nessun distruttore, intercetterà le eccezioni

0

Non è possibile rilevare come viene chiamata la propria funzione a meno che i chiamanti non forniscano tali informazioni.

Inoltre, come ricordo Visual C++ non è mai stato implementato std::uncaught_exception, in modo che sarebbe ungood (per codice portatile) anche dove era noto che nessun distruttore ha invocato alcun blocco try.

Tuttavia, è banale rilevare se un oscilloscopio viene chiuso a causa di un'eccezione o meno.

Inserire semplicemente tale ambito in un blocco try; questo è quello che è per

Per esempio,

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

Diniego: Non ho usato quel modello e quindi non in grado di attestare come pratica che è.

Problemi correlati