nested_exception
id:faith_and_brave:20081203 の InnerException を、nested_exception で書いてみた。
class my_nested : public exception { private: const char* what_; public: my_nested(const char* what) : what_(what) { } virtual const char* what() const throw() { return what_; } }; template<class T> void output_if_exception(T e) { if ((exception* ex = dynamic_cast<exception*>(e)) != nullptr) { cout << ex.what() << endl; } }
try { try { try { throw hoge_exception("Inner Inner Error!"); } catch (...) { throw_with_nested(my_nested("Inner Error!")); } } catch (...) { throw_with_nested(my_nested("Error!")); } } catch (my_nested& e) { output_if_exception(&e); try { rethrow_if_nested(e); } catch (my_nested& e2) { output_if_exception(&e2); try { rethrow_if_nested(e2); } catch (hoge_exception& e3) { output_if_exception(&e3); } } }
ただ、これは catch のところで my_nested と例外を特定してしまっているので、うまく書けてない。
catch (...) で受けて、exception にキャストできるなら表示としたい場合はよく分からない。
exception_ptr が dynamic_cast 出来るなら、こんな風に直感的に書けてもいいのだけれども……
try { try { try { throw hoge_exception("Inner Inner Error!"); } catch (...) { throw_with_nested(my_nested("Inner Error!")); } } catch (...) { throw_with_nested(my_nested("Error!")); } } catch (...) { output_if_exception(current_exception()); if ((nested_exception* ne1 = dynamic_cast<nested_exception*>(current_exception())) != nullptr) { output_if_exception(ne1.nested_ptr()); if ((nested_exception* ne2 = dynamic_cast<nested_exception*>(ne1.nested_ptr())) != nullptr) { output_if_exception(ne2.nested_ptr()); } } }
というかこっちを先に思いついたんだけど、exception_ptr って dynamic_cast できないんじゃね?と気がついて最初のやつに修正したという罠。
しかしよく考えてみると、dynamic_cast の代わりにこうやって書けそう。
template<class T> T* dynamic_exception_cast(exception_ptr p) { try { rethrow_exception(p); } catch (T& t) { return new T(t); } catch (...) { return nullptr; } }
void output_if_exception(exception_ptr e) { if ((exception* ex = dynamic_exception_cast<exception>(e)) != nullptr) { cout << ex.what() << endl; } }
try { try { try { throw hoge_exception("Inner Inner Error!"); } catch (...) { throw_with_nested(my_nested("Inner Error!")); } } catch (...) { throw_with_nested(my_nested("Error!")); } } catch (...) { output_if_exception(current_exception()); if ((nested_exception* ne1 = dynamic_exception_cast<nested_exception>(current_exception())) != nullptr) { output_if_exception(ne1.nested_ptr()); if ((nested_exception* ne2 = dynamic_exception_cast<nested_exception>(ne1.nested_ptr())) != nullptr) { output_if_exception(ne2.nested_ptr()); } } }
当然 new してるからリークするけど、うまくすればもう少し綺麗に書けるんじゃないかなーと思ったり。