11

これは、Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in 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
}

1つの試みは次のとおりです。

assert(!std::uncaught_exception());

ただし、オブジェクトがスコープ外になったために呼び出された場合ではなく、例外のためにデストラクタが呼び出された場合にのみ機能します。

4

2 に答える 2

1

これを検出することはできず、検出したくありません。それはあなたのクラスの仕事ではありません。誰かがnoexceptデストラクタからあなたに電話をかけると、彼は例外をキャッチします

于 2013-02-20T00:02:40.223 に答える
0

呼び出し元にその情報を提供させない限り、関数がどのように呼び出されたかを検出することはできません。

また、私が思い出すように、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;
    }
}

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

于 2013-02-18T18:08:08.520 に答える