#include #include #include namespace leaf = boost::leaf; struct e_failure_info { std::string value; }; enum custom_error_code { first_error = 1, second_error }; namespace boost { namespace leaf { template <> struct is_error_type : std::true_type {}; } // namespace leaf } // namespace boost void f1(unsigned behavior) { [[maybe_unused]] auto propagate = leaf::preload(e_failure_info{"f1"}); switch (behavior) { case 0: return; case 1: throw std::runtime_error("f1-1"); default: break; } } leaf::result f2(unsigned behavior) { if (behavior == 0) { return leaf::new_error(first_error); } if (behavior == 1) { throw std::runtime_error("f2-1"); } [[maybe_unused]] auto propagate = leaf::preload(e_failure_info{"f2"}); switch (behavior) { case 0: break; case 1: break; case 2: return leaf::new_error(second_error); case 3: throw std::runtime_error("f2-2"); default: f1(behavior - 4); break; } return behavior; } int main() { for (unsigned i = 0; i < 8; ++i) { std::cout << "\nf2(" << i << ")" << std::endl; leaf::handle_all( [i]() -> leaf::result { LEAF_AUTO(r, leaf::exception_to_result([i] { return f2(i); })); // LEAF_AUTO(r, f2(i)); (void)r; return 0; }, [](std::exception const &e, e_failure_info const &info) { std::cout << "error: exception: " << e.what() << " info: " << info.value << std::endl; return 1; }, [](custom_error_code ec, e_failure_info const &info) { std::cout << "error: code: " << ec << " info: " << info.value << std::endl; return 2; }, [](std::exception const &e) { std::cout << "error: exception: " << e.what() << std::endl; return 3; }, [](custom_error_code ec) { std::cout << "error: code: " << ec << std::endl; return 4; }, [](leaf::verbose_diagnostic_info const &error) { std::cout << "error: unmatched: " << error << std::endl; return 5; }); } return 0; }