15

ふと気がついた

http://en.cppreference.com/w/cpp/error/uncaught_exception

その C++17 は、 を返すをstd::uncaught_exception()、 を返すに置き換えます。boolstd::uncaught_exceptions()int

これを説明する標準への追加は次のとおりです。

http://isocpp.org/files/papers/n4259.pdf

それは根拠を提供しませんが、それは言います

[注: uncaught_exceptions() > 0 の場合、例外をスローすると std::terminate() (15.5.1) が呼び出される可能性があります。– エンドノート]

これは奇妙に曖昧です。

この変更の理由は何ですか? C++17 または標準の将来のバージョンでは、複数のアクティブな例外が可能になりますか?

4

3 に答える 3

22

これを紹介した論文はn4152であり、これには理論的根拠があります (これは一般的に「ScopeGuard を機能させる」ことに要約されます)。

引用すると、

少なくとも 1998 年以降、Guru of the Week #47 で文書化されているように、スタックの巻き戻し中に呼び出される可能性のあるデストラクタから推移的に呼び出されるコードは、それ自体が実際に巻き戻しの一部として呼び出されているかどうかを正しく検出できないことを意味します。例外の巻き戻しを開始すると、uncaught_exceptionアクティブな例外が複数ある場合でも、すべてが巻き戻しのように見えます。

これは、主要な実装に既に存在する情報を使用します。現在の ScopeGuard の実装は、文書化されていないコンパイラ機能に依存する移植性のないコードに頼って、今日 ScopeGuard を「実際に移植可能」にしています。このオプションは、コンパイラーに既に存在する情報を公開する単一の新しい関数を追加することを提案しているため、これらの使用法は真に移植可能です。

PS: コンパイラ固有の情報を使用してこの関数を実装する方法の例を次に示します: https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp

また、簡単な使用例としては、boost.log の「レコード ポンプ」を参照してください ( boost/log/detail/format.hppおよびboost/ log /sources/record_ostream.hppを参照)。BOOST_LOG(lg) << foo();ガードオブジェクトのデストラクタで、fooスローしない場合、つまり、デストラクタが呼び出されたときに飛行中の例外の数がコンストラクタが呼び出されたときよりも多くない場合に作成します。

于 2015-01-02T11:43:55.773 に答える