协程可以returnstd::future吗? (无法找到此协程的承诺类型)

Can coroutine return std::future? (unable to find the promise type for this coroutine)

我已经尝试从 CppCon 演示文稿中编译协程示例 https://youtu.be/ZTqHjjm86Bw?t=560

不幸的是编译失败:

$ g++-10 -pedantic -Wall -std=c++20 -fcoroutines main.cpp 
main.cpp: In function ‘std::future<int> compute_value()’:
main.cpp:7:16: error: unable to find the promise type for this coroutine
    7 |   int result = co_await std::async([]
      |                ^~~~~~~~

主持人一开始就警告说,他要展示的只是一个提案。所以这让我感到困惑:std::future 可以来自协程 return,还是我只是尝试错误地调用它?

完整代码:

#include <coroutine>
#include <iostream>
#include <future>

std::future<int> compute_value(){
  int result = co_await std::async([] 
  {
    return 30;
  });

  co_return result;
}

int main() {
    std::cout << compute_value().get() << std::endl;
}

C++20 中(基本上1)没有标准库类型实现必要的协程机制以使协程工作。 包括std::promise<T>/future<T>.

尽管如此,您可以为它们编写实现协程机制的包装器。

1:像std::suspend_always/never这样的support types有协程机制,但他们并没有像你想的那样做任何事情.

在 C++20 中,用户应手动启用 std::future<T> 作为协程类型。 std::future<int> 的最小完整示例:

#include <coroutine>
#include <future>
#include <iostream>

template <>
struct std::coroutine_traits<std::future<int>> {
  struct promise_type : std::promise<int> {
    std::future<int> get_return_object() { return this->get_future(); }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }
    void return_value(int value) { this->set_value(value); }
    void unhandled_exception() {
      this->set_exception(std::current_exception());
    }
  };
};

auto operator co_await(std::future<int> future) {
  struct awaiter : std::future<int> {
    bool await_ready() { return false; } // suspend always
    void await_suspend(std::coroutine_handle<> handle) {
      std::thread([this, handle]() {
        this->wait();
        handle.resume();
      }).detach();
    }
    int await_resume() { return this->get(); }
  };
  return awaiter{std::move(future)};
}

std::future<int> compute_value() {
  int result = co_await std::async([] { return 30; });

  co_return result;
}

int main() { std::cout << compute_value().get() << std::endl; }

参考:https://en.cppreference.com/w/cpp/coroutine/coroutine_traits