http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3279.pdf
にて、 C++0x の標準ライブラリにおける noexcept
指定の基準が示されたので、以下 適当に和訳。
- デストラクタには例外指定を付けない。
- その結果として、暗黙に指定された(例外を投げない)例外指定が使用される。
- 広い契約 ( Wide Contract ) を持った関数が、どのような状況であっても例外を投げない場合、条件式のない
noexcept
指定をつける。 swap
関数、ムーブコンストラクタ、ムーブ代入演算子が、条件付きで広い契約を持つ場合には、条件式を伴ったnoexcept
指定を付ける。 それ以外の関数に対しては、条件式を伴ったnoexcept
指定は行わない。- C との互換性の為に用意された関数には、条件式のない
noexcept
指定がされていてもよい。
ある関数が「広い契約を持つ」とは、その関数が どのような状況で呼ばれたとしても、決して未定義動作が起きない、ということ。
例えば std::vector
や std::vector
は広い契約を持つ。 このうち、前者は例外を投げることが無いため、条件式のない noexcept
によって例外指定が行われる。 後者は範囲外アクセスの際に例外を投げるので、 noexcept
による例外指定は行われない。
一方で std::vector
や std::vector
は、広い契約を持たない。 前者は空の場合に、後者は範囲外アクセスの場合に、それぞれ未定義動作となるためだ。 これらの関数に対して noexcept
指定は行われない。
// なお、未定義動作が起こり得る際に noexcept
を排除するのは、デバッグ用の都合。
// これにより、未定義動作が起こった場合には例外を投げる、という処理が可能になる。
// ムーブ時に条件付き noexcept
を許可するのは、ムーブに関しては
// 「例外が投げられる可能性の有無によって処理を切り替える」ケースが多いため。
// ムーブ時以外に条件付き noexcept
を排除しているのは、規格の不必要な複雑化を避けるためだろう。
// 個人的には、コンストラクタや代入演算子に関しては、ムーブに限らず、条件付き noexcept
指定が有ってもいいと思うが…。