cppreference でわかるように、古典的な「スロー」宣言リストはC++ 11で非推奨になりました。このメカニズムを終了する理由は何ですか?また、どの例外が私の機能をスローするかを指定する必要がありますか?
より詳細な推論については、以下を参照してください: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3051.html
上記の国家機関のコメントで表されているように、例外仕様は実際には有用ではありません。 C++の例外仕様に関する問題については多くの議論がありますが(たとえば、[Sutter02]、[Boost03]を参照)、主な問題は次のとおりです。
- 実行時チェック:C++例外仕様はコンパイル時ではなく実行時にチェックされるため、すべての例外が処理されたことをプログラマが保証することはできません。実行時障害モード(std :: unexpected()の呼び出し)は、回復に役立ちません。
- 実行時オーバーヘッド:実行時チェックでは、コンパイラが最適化を妨げる追加コードを生成する必要があります。
- 汎用コードでは使用不可:汎用コード内では、テンプレート引数の操作からスローされる例外のタイプを知ることは一般的に不可能であるため、正確な例外仕様を記述することはできません。
実際には、2つの形式の例外スロー保証のみが有用です。1つの操作が例外(任意の例外)をスローする場合と、1つの操作が例外をスローしない場合があります。前者は例外仕様を完全に省略することで表現され、後者はthrow()として表現できますが、パフォーマンスを考慮するとめったにありません。
[N3050]は、新しい種類の例外仕様、noexceptを導入します。これは、関数が例外をスローしないことを指定します。 throw()とは異なり、noexceptでは、例外がスローされるかどうかをチェックするコードをコンパイラーに導入する必要がありません。むしろ、noexceptとして指定された関数が例外を介して終了した場合、結果はstd :: terminate()の呼び出しになります。
Noexceptの導入により、プログラマは、追加のオーバーヘッドなしで、実際に役立つ2種類の例外保証を表現できるようになりました。したがって、このペーパーでは、「動的な」例外仕様、つまりthrow(type-id-listopt)として記述された仕様を廃止することを提案します。
Peterが与えた答えは、実装者とユーザーの例外仕様の実際の問題には当てはまりません。
結論は、C++がJavaがやった方法を行ったはずだということです。
Noexcept(C++ 11以降)は、同じ概念上の誤りに悩まされます。仕様が守られていない場合、つまり、宣言されていないメソッドがスローされた場合、ランタイム終了も発生するためです。これにより、noexcept
を使用して、深刻な場合以外は使用できなくなります( 移動コンストラクターが思い浮かぶ )。
Libc ++は、関数から伝播する例外がその例外仕様に違反しているかどうかをチェックし、std::unexpected
。これはほとんど役に立たず、関数が自分でスローする例外を単に文書化するよりも悪いです。