関数try
ブロック
WILのGitHub Wikiを読んでいたら関数名の後ろ、const
やnoexcept
のある部分にtry
、関数の直後にcatch
のあるコードを見かけました。main
関数で示せば次のような感じです。
#include <exception> int main() try { throw std::exception(); } catch (...) { return 1234; }
上記の構文はFunction-try-block(関数tryブロック)というそうです。main
で発生した未捕捉の例外はmain
直後のcatch
文で捕捉されます。上のコードは終了コード1234
で正常終了します。
WILでの利用
例外の捕捉コストはある気がしますが、WILでは例外をHRESULT
へ変換したりその逆を行うマクロなどで使用されています。関数内に毎回try-catch
を書くより、関数名後ろのtry
とブロック直後のマクロを書く方がたしかに簡潔だと思います。
MSVCのコンストラクタにおける不思議な挙動
MSVC(Visual Studio C++ 2019)では不思議な挙動がありました。コンストラクタ内部で発生した例外は呼び出し側がtry
を使っている場合は関数try
ブロックでも適切に処理され、try
を使っていない場合はコンストラクタ内部のthrow
で強制終了しました。コンストラクタやデストラクタはそもそも例外を伝播させない設計が求められていたと思うので、使用時は注意が必要かもしれません。
#include <exception> #include <iostream> struct test_class { test_class() try { throw std::exception(); } catch (...) { std::cout << "test_class::test_class() function-try-block" << std::endl; } }; int main() { try { test_class t; } catch (...) { std::cout << "main() function-try-block" << std::endl; } // 出力: // test_class::test_class() function-try-block // main() function - try - block test_class t; // 出力: // ※test_class::test_class()のthrow行でハンドルされない例外により強制終了。 return 0; }