std::async(std::launch::deferred) + std::future::then 的行为

behaviour of std::async(std::launch::deferred) + std::future::then

延迟未来背后的想法(只能通过使用 std::launch::deferred 标志调用 std::async 来实现)是只有当有人试图等待或提取未来值或异常时才会调用回调未来。到那时回调还没有执行。

如果我使用 std::future::then 将延续附加到延迟的未来会怎样?延迟的未来会丢失(then 使未来无效)并返回一个新的未来。

这样的话,按照标准,应该怎么办?新的未来也是延迟的未来吗?它会陷入僵局吗?最新文档中没有解决这个问题。

在我看来,这似乎是 the TS 中的一个错误。或者至少是一个记录不足的陷阱。

这是来自 TS 的文本:

2.3 [futures.unique_future]/6-10

template <class F>
see below then(F&& func);

Requires:

INVOKE(DECAY_COPY (std::forward<F>(func)), std::move(*this)) shall be a valid expression.

Effects:

The function creates a shared state that is associated with the returned future object. Additionally,

When the object's shared state is ready, the continuation INVOKE(DECAY_COPY(std::forward<F>(func)), std::move(*this)) is called on an unspecified thread of execution with the call to DECAY_COPY() being evaluated in the thread that called then.

Any value returned from the continuation is stored as the result in the shared state of the resulting future. Any exception propagated from the execution of the continuation is stored as the exceptional result in the shared state of the resulting future.

Returns:

When result_of_t<decay_t<F>(future<R>)> is future<R2>, for some type R2, the function returns future<R2>. Otherwise, the function returns future<result_of_t<decay_t<F>(future<R>)>>. [ Note: The rule above is referred to as implicit unwrapping. Without this rule, the return type of then taking a callable returning a future<R> would have been future<future<R>>. This rule avoids such nested future objects. The type of f2 below is future<int> and not future<future<int>>:

[ Example:

future<int> f1 = g();
future<int> f2 = f1.then([](future<int> f) {
                    future<int> f3 = h();
                    return f3;
                 });

— end example ]

— end note ]

Postconditions:

valid() == false on the original future. valid() == true on the future returned from then. [ Note: In case of implicit unwrapping, the validity of the future returned from thenfunc cannot be established until after the completion of the continuation. If it is not valid, the resulting future becomes ready with an exception of type std::future_error, with an error condition of std::future_errc::broken_promise. — end note ]

延迟的未来任务没有特殊情况。如果延迟的未来任务在调用 .then 之前没有就绪,则无法使其就绪,因此无法调用 func 的衰减副本。

shared_future的文字类似;在那里,您仍然可以在调用 .then 之后使 shared_future 准备就绪。

如果这是有意的; .then 在未就绪的延迟唯一未来将导致 future 的 return 值永远无法准备好 - 这应该在 TS/standard 中明确.如果不是这样,则需要更改标准文本。

请注意,这些更改未出现在 2018 年发布的 N4762 draft standard 中。

我不确定标准应该如何解决这个问题; .then 语义对于 shared_future 是合理的,但对于 future 则不合理,不同的语义会令人惊讶。