std::future::unwrap 异常传播竞赛

Race in exception propagation with std::future::unwrap

在此处 n3721 结束有关 std::future 的 API 改进的论文。关于未包装的期货,异常传播似乎存在竞争。该文件说

If the outer future throws an exception, and .get() is called on the returned future, the returned future throws the same exception as the outer future. This is the case because the inner future didn’t exit

所以我的意思是像下面这样的情况

#include <iostream>
#include <future>
#include <exception>

using namespace std;

int main() {
    auto prom_one = std::promise<std::future<int>>{};
    auto fut_one = prom_one.get_future();

    std::thread{[prom_one = std::move(prom_one)]() mutable {
        auto prom_two = std::promise<int>{};
        auto fut_two = prom_two.get_future();
        std::thread{[prom_two = std::move(prom_two)]() mutable {
            prom_two.set_exception(std::make_exception_ptr(std::logic_error{}));
        }}.detach();
        prom_one.set_exception(std::make_exception_ptr(std::bad_alloc{}));
    }}.detach();


    auto inner_fut = fut_one.unwrap();
    cout << inner_fut.get() << endl;

    return 0;
}

我之前说的竞赛是——会抛出哪个异常?内std::logic_error还是外std::bad_alloc

我理解错了吗?上面的代码没有race吗?

我意识到上面的代码没有任何竞争,因为有一个嵌套的未来 - std::future<std::future<int>> 只有两种可能性,要么通过调用 std::promise::set_value 设置内部未来或者已经设置了一个例外,并且内部未来与外部未来根本没有联系(如上面的代码所示)。

如果内部未来尚未链接,则外部未来的异常将被抛出。如果内部未来已经链接,外部未来就没有抛出的范围,因为外部未来的承诺已经用内部未来调用 set_value 一次,所以在外部未来本身之后设置异常是无效的(这将导致异常本身被抛出)。

我想这就是这篇论文所说的

This is the case because the inner future didn’t exit