Поскольку Coroutines TS был принят в C ++ 20 на встрече ISO в Kona, я начал немного поиграться с ними для себя. Clang уже имеет приличную поддержку сопрограмм, но реализация поддержки библиотеки все еще отсутствует. В частности, еще не реализованы типы Awaitable, такие как std::future
, std::generator
и т. Д.
Таким образом, я взял на себя задачу сделать std::future
ожидаемым. Я в основном следил за докладом Джеймса МакНеллиса на CppCon 2016, в частности, за этим слайдом:
В 2019 году у меня действительно возникли проблемы с (предположительно непроверенным?) Кодом на этом слайде:
- Мне кажется, перегрузка
operator co_await
уже не актуальна? Вместо этого следует использовать необязательныйawait_transform
изpromise_type
. Хотя не уверен, что правильно понял. - Продолжение
then
future захватывает дескриптор по значению, но функция-членresume
не квалифицируется как const. Я обошел это, сделав лямбдаmutable
.
Кроме того, then
и is_ready
недоступны в std::future
, но являются частью std::experimental::future
, который является все еще отсутствует в моей версии libc ++. Чтобы избежать работы с Awaiter и реализовать будущие продолжения, я написал производный класс future, который является Awaitable и Awaiter. Насколько я понимаю, в конечном итоге и то, и другое будет верным и для std::future
. Вы можете увидеть мой пример в Compiler Explorer. Он компилируется.
Однако он также имеет segfault. Это происходит в await_resume
, когда вызывается get()
. На самом деле это не удивительно, поскольку valid()
в этот момент возвращает false
(вызывая get()
UB). Я думаю, это связано с тем, что когда then
используется для продолжения будущего, исходный объект future перемещается в асинхронное будущее, тем самым делая недействительным старое будущее (*this
во время вызова await_resume
, то есть после перемещения). Моя реализация then
во многом вдохновлена этим ответом и этот код, который я нашел на GitHub. Возможно, они не идеальны, но cppreference явно указывает valid() == false
как постусловие для звонит then
, поэтому я считаю правильным выйти из первоначального будущего.
Что мне здесь не хватает? Эта «ошибка», кажется, уже присутствует на слайде выше. Как я могу решить эту проблему? Кто-нибудь знает (работающую) существующую реализацию Awaitable будущего? Спасибо.