MLに面白い話題が上がっていたので紹介する。
noexceptには、二つの意味がある。
1. 例外指定としてのnoexcept
void f() noexcept ; // noexcept(true)と同じ void g() noexcept(true) ; // 例外を投げない void h() noexcept(false) ; // 例外を投げる
この場合、文法は、noexcept( 定数式 )という文法になる。定数式がtrueと評価されれば、無例外といういみである。
2. noexcept演算子
void f() ; void g() noexcept ; int main() { noexcept( f() ) ; // false noexcept( g() ) ; // true }
この場合、文法は、noexcept( 未評価式 )となる。未評価式が例外を投げる可能性があれば、falseを返す。例外を投げないと保証できる場合は、trueを返す。例外を投げる可能性というのは、throw式が含まれているかや、noexcept(true)と指定されていない関数を呼び出すかどうかで判断される。たとえ、実際にはthrow式が含まれていなくても、無例外指定がされていない関数の呼び出しは、falseと評価される。noexcept演算子は、定数式である。
さて、以下の例を考えてみよう。
void f() noexcept( noexcept( g() ) ) ;
これはどういう意味かというと、g()という未評価式が、例外を投げる可能性がなければ、関数fは無例外指定されるという意味である。一方、
void f() noexcept( g() ) ;
これは、g()という定数式が、trueと評価された場合に、関数fは無例外指定になるという意味である。もちろん、g()という式が定数式でなければ、エラーとなる。
この文法はどう考えてもややこしくないか。
実は、以下のような文法も考慮されていたらしい。
void f() noexcept if true ;
ここでは、ifというキーワードを使うことによって、次に定数式を指定している。しかし、noexcept(true)の方が分かりやすいという意見の方が多かったため、こうなった。また、別の拡張で、似たような文法を使いたい時に困るという意見もあった。別の拡張というのは、ほかでもない、明示的なSFINAEである。
No comments:
Post a Comment