C++1z 例外仕様を型システムの一部にする

C++1zからは、noexceptによる関数の例外仕様が、型の一部として扱われるようになります。

互換性のためにnoexceptな関数ポインタから非noexceptな関数ポインタには変換できます。しかし、非noexceptな関数ポインタからnoexceptな関数ポインタには、変換できません。

void f() noexcept;
void g();

void(*p1)() noexcept = f;   // OK
void(*p2)() = f;            // OK : noexceptから非noexceptへの変換
//void(*p3)() noexcept = g; // コンパイルエラー : 非noexceptからnoexceptに変換できない

これは、ラムダ式も同様になります。

void(*p1)() noexcept = []() noexcept {}; // OK
void(*p2)() = []() noexcept {};          // OK
//void(*p3)() noexcept = [](){};         // コンパイルエラー

noexceptの違いによって関数をオーバーロードすることはできません。(戻り値の型と同様)

この仕様による破壊的な影響として、C++14まで有効だった以下のコードは、C++1zではコンパイルエラーになります:

void g1() noexcept;
void g2();

template<class T>
int f(T*, T*);

int x = f(g1, g2); // コンパイルエラー : g1とg2の型が一致しない (関数テンプレートの推論失敗)

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。