(以下は私の英語力と理解といい加減なまとめによる産物です.正確な記述は『More Exceptional C++』の原文を参照してください.)
「なんか書いてあったな〜」じゃあ情報量ほぼ0なので追記.
以下は http://diary.imou.to/~AoiMoe/2008.02/early.html#2008.02.05_s02 の内容を理解していることを前提にした文章です.
More Exceptional での基本的な論調は以下の2点.
まず技術的な論点として,「std::uncaught_exception が使えるんじゃないの?」という指摘が考えられる.実際,例外が active なのかどうなのかは std::uncaught_exception で判断できるので,
class file_out { FILE *fp; public: file_out(FILE *afp) : fp(afp) { } ~file_out() { if (fclose(fp) && !std::uncaught_exception()) throw WriteError(); } void putc(int ch) { if (fputc(ch, fp) == EOF) throw WriteError(); } }; void foo() { file_out fo("foo.txt"); fo.putc('c'); }
と書けばよいように一見思われる.だけど,
class U { // ... public: ~U() { try { file_out fo("foo.txt"); // ... } catch (...) { // ... } } };
こういうクラス U があったときに, U のオブジェクトのデストラクタが stack unwinding で呼ばれた際には, file_out::~file_out における std::uncaught_exception は false を返す (が実際にはそこで例外を投げると2重例外であぼーん) ので期待通りの動作はしない.したがって「上記のような std::uncaught_exception は期待通りに動作しないので,こういう std::uncaught_exception の使い方はダメ」が1点.
(しお兄ちゃんさんが ~file_out() catch (...) という構文にどういう semantics を持たせたいのかが明瞭じゃないので,上の点に関してはしお兄ちゃんさんに対するレスポンスとして適当でない可能性はある)
もう1つは設計からの観点.デストラクタが例外を投げる場合と投げない場合の2通り存在するのは,「デストラクタに2つの責任,つまり『エラーを通知する close』と『エラーを通知しない close』を同時に持たせようとしている」 (デストラクタのエラー通知方法が場面場面で異なり,これは責任を分け切れていない) という指摘.デストラクタにはエラーを通知せずリソースの開放のみを行う責任を持たせ,エラーの通知を行う close を別に書け,というもの.エラーの通知が欲しければ,エラーを通知してくれる close を明示的に書きなさい,と.
class file_out { FILE *fp; public: file_out(FILE *afp) : fp(afp) { } ~file_out() { try{ close(); } catch(...){ } } void putc(int ch) { if (fputc(ch, fp) == EOF) throw WriteError(); } void close() { if (fp && fclose(fp)) throw WriteError(); fp = NULL; } }; void foo() { file_out fo("foo.txt"); fo.putc('c'); fo.close(); // これは「リソースを開放しろ」というよりは「リソースの開放時にエラーが生じるようならそれを通知しろ」 }
まあ,これも個人的にはあんまり納得していないけれど.