Created
October 30, 2015 01:24
-
-
Save mrdomino/508899a5ec91fe9f71e8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <cstdio> | |
| #include <exception> | |
| #include <utility> | |
| // hypothetically... | |
| class MyException : public std::exception { | |
| public: | |
| const char *what() const noexcept { | |
| return "nope"; | |
| } | |
| }; | |
| template <typename F, typename E, typename R> | |
| class NoexceptWrap_ { | |
| public: | |
| using func_type = F; | |
| using error_type = E; | |
| using return_type = R; | |
| R operator()(F&& f, E&& handle, R&& fail_return) { | |
| using std::exception; | |
| using std::forward; | |
| try { | |
| return forward<F>(f)(); | |
| } catch (MyException const& e) { | |
| try { forward<E>(handle)(e); } catch (...) {} | |
| } catch (exception const& e) { | |
| try { forward<E>(handle)(e); } catch (...) {} | |
| } catch (...) { | |
| try { forward<E>(handle)(); } catch (...) {} | |
| } | |
| return forward<R>(fail_return); | |
| } | |
| }; | |
| template <typename F, typename E> | |
| class NoexceptWrap_<F, E, void> { | |
| public: | |
| using func_type = F; | |
| using error_type = E; | |
| using return_type = void; | |
| void operator()(F&& f, E&& handle) { | |
| using std::exception; | |
| using std::forward; | |
| try { | |
| forward<F>(f)(); | |
| } catch (MyException const& e) { | |
| try { forward<E>(handle)(e); } catch (...) {} | |
| } catch (exception const& e) { | |
| try { forward<E>(handle)(e); } catch (...) {} | |
| } catch (...) { | |
| try { forward<E>(handle)(); } catch (...) {} | |
| } | |
| } | |
| }; | |
| class PrintError { | |
| public: | |
| void operator()(MyException const& e) { | |
| printf(".%s\n", e.what()); | |
| } | |
| void operator()(std::exception const& e) { | |
| printf("!%s\n", e.what()); | |
| } | |
| void operator()() { | |
| printf("?\n"); | |
| } | |
| }; | |
| template <typename F, typename E> | |
| using NoexceptWrap = NoexceptWrap_<F, E, decltype(std::declval<F>()())>; | |
| template <typename F, typename E> | |
| auto noexcept_wrap(F&& f, E&& e, typename NoexceptWrap<F, E>::return_type&& fail_return) | |
| -> typename NoexceptWrap<F, E>::return_type { | |
| using std::forward; | |
| using return_type = typename NoexceptWrap<F, E>::return_type; | |
| static NoexceptWrap<F, E> wrap; | |
| return wrap(forward<F>(f), forward<E>(e), forward<return_type>(fail_return)); | |
| } | |
| template <typename F, typename E> | |
| void noexcept_wrap(F&& f, E&& e) { | |
| using std::forward; | |
| static NoexceptWrap<F, E> wrap; | |
| wrap(forward<F>(f), forward<E>(e)); | |
| } | |
| int main() { | |
| noexcept_wrap([] { throw MyException(); }, PrintError()); | |
| noexcept_wrap([] { throw std::exception(); }, PrintError()); | |
| printf("%d\n", noexcept_wrap([] { return 0; }, PrintError(), 1)); | |
| printf("%d\n", noexcept_wrap([] { throw "wow"; return 0; }, PrintError(), 1)); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment