#pragma warning(disable : 4275) #pragma warning(disable : 4251) #include #include #include #include #include #include #include #include namespace details { template struct caller_impl { template static void call(Function f, Result *res) { *res = f(); } }; template<> struct caller_impl { template static void call(Function f, Result *res) { try { typedef boost::mpl::pop_front::type popped; caller_impl::value>::call(f, res); } catch (boost::mpl::front::type e) { *res = e; } } }; template class caller { public: caller(ThreadFunc f, ResultsType & res) : f_(f), res_(res) { } void operator()() { try { // remove the return value type, all of the rest are exception types to be caught typedef typename boost::mpl::pop_front::type popped; caller_impl::value>::call(f_, &res_); } catch (...) { res_ = std::bad_exception(); } } private: ThreadFunc f_; ResultsType & res_; }; } template class async_call { typedef typename boost::variant result_types_; public: template async_call(ThreadFunc thread_func) : thr_(details::caller(thread_func, res_)) { } ReturnType result() { thr_.join(); if (const ReturnType* p = boost::get(&res_)) { return *p; } boost::apply_visitor(rethrower(), res_); // unreachable code, but the compiler isn't so sure and warns us. throw std::bad_exception(); } private: struct rethrower : boost::static_visitor<> { template void operator()(Exception e) const { throw e; } }; result_types_ res_; boost::thread thr_; }; int do_throw() { throw std::exception("an exception"); } int dont_throw() { return 42; } int throw_unexpected() { throw std::string(); } template void test(Function function) { try { async_call async(function); std::cout << "Test Result = " << async.result() << std::endl; } catch (std::exception e) { std::cout << "Exception caught : " << e.what() << std::endl; } } int main() { test(do_throw); test(dont_throw); test(throw_unexpected); }