将std :: exception_ptr转换为boost :: exception_ptr

kis*_*ljr 6 c++ boost c++11

我想使用boost::promise::set_exception()那个期待的boost::exception_ptr.问题是,boost:exception_ptr只有当我把所有的投掷包裹起来enable_current_exception并且我想避免这种情况时,似乎才能正常工作.(我不能够做到这一点的第三方库反正)我用std::exception_ptr/std::current_exception在我的代码,所以我正在寻找一种方式来传递std::exception_ptr,其中一个boost:exception_ptr预期.执行以下操作的东西,但编译:

boost::exception_ptr convert(std::exception_ptr ex) {
    try {
        std::rethrow_exception(ex);
    }
    catch(auto& ex) {
        try {
            throw boost::enable_current_exception(ex);
        }
        catch (...) {
            return boost::current_exception();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你知道怎么做吗?

语境:

我需要boost::future::then(),所以使用a std::promise很遗憾不是一种选择(至少在目前)

如果你知道一种boost::exception_ptr依赖gcc 4.8编译器支持的方法enable_current_exception,那么这也是一种可接受的解决方案

mar*_*n78 3

不幸的是,我认为这是不可能的。不过,我可以为您提供三种可能的解决方案,按方便程度排序:

1. 捕获 std::Exception

boost::exception_ptr convert(std::exception_ptr ex)
{
    try {
        std::rethrow_exception(ex);
    } catch (const std::exception& e) {
        try {
            throw boost::enable_current_exception(e);
        } catch (...) {
            return boost::current_exception();
        }
    } catch (...) {
        try {
            throw boost::enable_current_exception(std::runtime_error("Unknown exception."));
        } catch (...) {
            return boost::current_exception();
        }
    }
}

int main()
{
    std::exception_ptr sep;

    try {
        throw std::runtime_error("hello world");
    } catch (...) {
        sep = std::current_exception();
    }

    boost::exception_ptr bep = convert(sep);

    try {
        boost::rethrow_exception(bep);
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }

}
Run Code Online (Sandbox Code Playgroud)

这将打印"std::exception"而不是"hello world",因为来自派生类(在本例中为std::runtime_error)的信息将被切掉。

2.直接抛出std::exception_ptr

boost::exception_ptr convert(std::exception_ptr ex)
{
    try {
        throw boost::enable_current_exception(ex);
    } catch (...) {
        return boost::current_exception();
    }
}

int main()
{
    std::exception_ptr sep;

    try {
        throw std::runtime_error("hello world");
    } catch (...) {
        sep = std::current_exception();
    }

    boost::exception_ptr bep = convert(sep);

    try {
        boost::rethrow_exception(bep);
    } catch (const std::exception_ptr& ep) {
        try {
            std::rethrow_exception(ep);
        } catch (const std::exception& e) {
            std::cout << e.what() << std::endl;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

此版本打印,尽管需要额外/块"hello world"的成本。如果错误处理是在中心位置完成的,可能会显示一个对话框,我会选择这个解决方案。恐怕在 boost 作者添加一个构造函数 from to之前,这已经是最好的了。trycatchstd::exception_ptrboost::exception_ptr

使用 boost::packaged_task 而不是 boost::promise

如果您可以接受使用packaged_task,则此解决方案有效:

#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>

int main()
{
    boost::packaged_task<int()> pt([] () -> int {
        throw std::runtime_error("hello world");
    });
    boost::future<int> f1 = pt.get_future();
    boost::future<int> f2 = f1.then([] (boost::future<int> f) {
        return f.get() + 1;
    });

    boost::thread(std::move(pt)).detach();

    try {
        int res = f2.get();
    } catch (const std::runtime_error& e) {
        std::cout << e.what() << std::endl;
    }

}
Run Code Online (Sandbox Code Playgroud)

打印"hello world"并允许您使用fut.then()