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

时间:2014-02-25 09:52:01

标签: c++ boost c++11

我想使用期望boost::promise::set_exception()的{​​{1}}。问题是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(); } } } ,所以遗憾的是,使用boost::future::then()不是一种选择(至少在目前)

如果您知道如何让std::promise依赖gcc 4.8编译器支持而不是boost::exception_ptr这是一个可接受的解决方案,那么

1 个答案:

答案 0 :(得分:2)

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

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;
    }

}

这会打印"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;
        }
    }

}

此版本打印"hello world",但需要额外try / catch块。如果在中心位置进行错误处理,可能会显示一个对话框,我会选择此解决方案。直到推文作者添加一个std::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;
    }

}

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