如何使用boost :: future抛出std :: exception_ptr存储的原始异常?

时间:2018-08-27 16:30:50

标签: c++ multithreading boost boost-thread

这是一个最小的代码示例,如何使用std :: exception_ptr:来处理异常。

#include <iostream>

#include <boost/thread.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>

int main() {
    try
    {
        throw std::runtime_error("Error!");
    }
    catch (...)
    {
        boost::optional<boost::variant<int, std::exception_ptr>> v(std::move(std::current_exception()));
        boost::promise<int> p;
        boost::future<int> f = p.get_future();

        try
        {
            std::rethrow_exception(std::move(boost::get<std::exception_ptr>(std::move(v.get()))));
        }
        catch (...)
        {
            p.set_exception(std::move(std::current_exception()));
        }

        try
        {
            f.get();
        }
        catch (const std::exception &e)
        {
            // This is what I would like to see:
            std::cerr << "Error: " << e.what() << std::endl;
        }
        catch (...)
        {
            // This is what I get instead:
            std::cerr << "Unknown error" << std::endl;
        }
    }

    return 0;
}

我想保留实际的对象std :: runtime_error并将其扔到最后的f.get()语句中。相反,我得到了一个未知异常,它不是从std :: exception派生的。 当我删除最终的catch(...)语句时,得到以下输出:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<std::__exception_ptr::exception_ptr>'

我想避免任何克隆/复制操作。我想保留我的std :: runtime_error实例并将其移动到结尾(最后的f.get()调用)。 如果有比std :: exception_ptr更好的方法来存储任何异常,请告诉我,我将改用它。 Folly使用类模板folly :: exception_wrapper,但我不知道其他任何标准类型。

您可以在此处检出原始项目的文件:https://github.com/tdauth/cpp-futures-promises/tree/master/src/advanced 需要不同的重新抛出,因为我使用了包装类型Try和方法Promise :: tryComplete。

1 个答案:

答案 0 :(得分:0)

它似乎可以与https://www.boost.org/doc/libs/1_68_0/libs/exception/doc/boost-exception.html

一起使用

我不应该在Boost.Thread中使用std :: exception_ptr。

此功能也有一张封闭(无法修复)的票证:https://svn.boost.org/trac10/ticket/9710

这个问题是如何进行转换的:Converting std::exception_ptr to boost::exception_ptr