2013-02-18 1 views
11

これは私が誰かが別のクラスのデストラクタでMyClassを作成(またはどこかの呼び出しスタック内のアクティブなデストラクタで)されたかどうかを検出したいWhy can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?別のデストラクタの実行中にオブジェクトが作成されたかどうかを検出するトリックはありますか?

のフォローアップの一種です。

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()); 

が、デストラクタは、オブジェクトがスコープ外に行ってきましたので、それが呼び出されていない場合は、例外のため、呼び出されている場合にのみ動作します。

+7

デストラクタを明示的に設計して実行をシグナルすることができない限り、これは可能です。一般的に、あなたの関数がどこから呼び出されたのかを知ることはできません。 –

+0

あなたはどのようにポータブルソリューションをしたいですか? – Flexo

+0

あなたのソリューションを特定のコンパイラバージョンに特化させ、 'OtherClass'のデストラクタを見つけるために' MyClass'のコンストラクタでスタックを調べることができます。私は個人的には、それが何かのためにはあまりにも多くの仕事だと思っています...そして、エラーの原因になります。 – Synxis

答えて

1

これは検出できません。それはあなたのクラスのビジネスではありません。誰かがnoexceptデストラクタからあなたを呼び出すと、彼は例外をキャッチします。

0

呼び出し元がその情報を提供しない限り、関数の呼び出し方法を検出することはできません。

また、Visual C++は決してstd::uncaught_exceptionを実装していないので、デストラクタが何もtryブロックを呼び出していないことがわかっていたとしても、(移植性のあるコードのために)うまくいきません。

ただし、例外のためにスコープが終了したかどうかを検出するのは簡単です。

そのスコープをtry -blockに入れるだけです。それが何のためだ。例えば

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

免責事項:私はそのパターンを使用していないので、それがどのように実用的に証明することはできません。

関連する問題