#ifndef TEST_EXCEPTION_TRANSPORTER_H_ #define TEST_EXCEPTION_TRANSPORTER_H_ #include #include #include #include #include namespace test { namespace detail { template struct base_transporter { typedef typename FunctionType function_type; typedef typename Result result_type; static void call(function_type f, result_type&) { f(); } static result_type call(function_type f) { return result_type(f()); } }; template struct one_exception_transporter : Base { typedef typename Base::function_type function_type; typedef typename Base::result_type result_type; static void call(function_type f, result_type& v) { try { Base::call(f, v); } catch (const Exception& e) { v.reset(e); } } static result_type call(function_type f) { try { return Base::call(f); } catch (const Exception& e) { return result_type(e); } } }; } template struct exception_transporter { typedef boost::function function_type; typedef typename boost::make_variant_over::type exception_variant_type; typedef typename boost::is_same::type is_void; typedef typename boost::mpl::if_< is_void, boost::optional, boost::variant >::type result_type; exception_transporter(const function_type& f_) : f(f_) { } result_type operator()() const { return boost::mpl::if_< is_void, call_void, call_non_void >::type::call(f); } typedef typename boost::mpl::fold< ExceptionList, detail::base_transporter, detail::one_exception_transporter >::type exception_handler_type; private: struct call_void { template static result_type call(Fun f) { result_type rval; exception_handler_type::call(f, result); return rval; } }; struct call_non_void { template static result_type call(Fun f) { return exception_handler_type::call(f); } }; boost::function f; }; } #endif /* TEST_EXCEPTION_TRANSPORTER_H_ */