2011-02-10 12 views
4

私はいくつかの方法が、以下の(そしてもっと)を好き持つクラスを持っている:RAIIを使用してキャッチを試みますか?

template<class T> 
    Logpp& operator<<(T const& obj) 
    { 
     *p_Stream << obj ; 
     return *this ; 
    } 

    Logpp& operator<<(char const* zString) 
    { 
     *p_Stream << zString ; 
     return *this ; 
    } 

    Logpp& operator<<(std::ostream& (*manip)(std::ostream&)) 
    { 
     *p_Stream << manip; 
     return *this ; 
    } 

私は、フォームのトライcatchブロック内の関数の本体を囲みたい:

Logpp& operator<<(std::ostream& (*manip)(std::ostream&)) 
    { 
     try 
     { 
      *p_Stream << manip; 
      return *this; 
     } 
     catch(ios_base::failure& e) 
     { 
      //MyException has a stringstream inside and can use operator<< 
      throw MyException("IO failure writing to log file : ") << e.what() << endl; 
     } 
    } 

Q1:このような例外を使用することをお勧めしますか? (各機能で)。私は例外を使用することに慣れていないので、わからない。

質問2:Q1への回答が肯定的な場合、冗長性を取り除くためにこれを行うことはできますか?

Logpp& operator<<(std::ostream& (*manip)(std::ostream&)) 
    { 
     Catch<ios_base::failure> tc(); 
     try 
     { 
      *p_Stream << manip; 
      return *this; 
     } 
     //destructor of tc will be written to catch the template exception type and rethrow as a MyException. 
    } 
+0

私はファイルとライン情報を埋め込むマクロと同様のことをします。マクロも使えますか? – Anycorn

+0

テンプレート以外のオーバーロードがテンプレート関数と同じになるのはなぜですか?彼らはすべてインラインであるので、彼らは非参照として彼らの議論を取ることは重要ではありません。 – MSalters

答えて

6

Q1:それはこのような例外を使用することをお勧めしますか? (各機能で)。私は例外を使用することに慣れていないので、わからない。

特に問題はありませんが、例外情報を充実させたり、いくつかのios_base :: failure関数を他のものと区別したりしない限り、特別な理由はありません。各関数を大きく/複雑にしたいそれが他の何かを小さくする/より単純にするなら。

質問2:Q1への回答が肯定的な場合、冗長性を取り除くためにこれを行うことはできますか?

マクロを使用してtry/catchブロックを生成する可能性があります。あなたが提案したことをすれば、例外が処理されている間、デストラクタが呼び出されます:再度スローしようとすると、terminate()が呼び出されます。詳細については、C++ Liteのよくある質問を確認してください:Q1へhttp://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9

3

回答:Q2へMEH ...

回答:いいえ、デストラクタ本体は常に実行され、任意の例外データを受信しませんが。このようにしてcatch節を置き換えることはできません。

可能であれば、RAIIという用語には該当しません。 RAIIに似ていますが、自動メモリルールを使用すると特定のことが起こることがありますが、それはそれです。どこがされている(R)esource(A)が...例えば、quiredだ

3

広告Q1:私は少しそれに対してお勧めします

。ラップ例外は、最終的に例外を処理する呼び出し側が内部の詳細を知ってはならず、元の例外がそれに意味をなさない場合に実行する必要があります。しかしoperator<<を投げるとstd::ios_base::failureは完璧な意味合いがあるので、私はここでラップしません。

広告Q2:

ありませんが、あなたが何かを行うことができます:

Logpp& do_output(std::ostream& (*manip)(std::ostream&)) 
{ 
    *p_Stream << manip; 
    return *this; 
} 

Logpp& operator<<(std::ostream& (*manip)(std::ostream&)) 
{ 
    return wrap_exception(&Logpp::do_output, this, manip); 
} 

を(おそらく

return wrap_exception(bind(&Logpp::do_output, this, manip)); 
0

ラッピング例外としてTR1 /ブーストから少し簡単に利用バインドがありますあなたが必要と確信している場合にのみ行うべきことのようなものです。通常は役に立ちません。

あなたはデストラクタから例外をキャッチすることはできませんが、次の操作を行うことができます。

void handleCurrentException() 
{ 
    try { throw; } // rethrow currently active exception 
    catch (ios_base::failure& e) 
    { 
    // exception handling/rethrowing code 
    } 
} 

Logpp& operator<<(std::ostream& (*manip)(std::ostream&)) 
{ 
    try 
    { 
    *p_Stream << manip; 
    return *this; 
    } 
    catch(...) 
    { 
    handleCurrentException(); 
    } 
} 

ここで再スローコードが短いので、それはそれだけの価値はないかもしれません。例外処理コードが長い場合は有益です。

関連する問題