Не пустые сопрограммы без возврата
Я пытаюсь обернуть голову вокруг функции сопрограммы C++. Я прочитал статью Кенни ( C++ - Представляем C++ / WinRT), а также попытался посмотреть эту презентацию, CppCon 2016: Джеймс МакНеллис "Введение в сопрограммы C++". Я продолжаю видеть "пустые" "функции" без какой-либо формы выражения return. В качестве примера см. следующий пример кода из статьи Кенни: Функция / сопрограмма PrintFeedAsync имеет тип возврата IAsyncAction, но в определении нет оператора возврата. Может кто-нибудь объяснить, как это работает?
IAsyncAction PrintFeedAsync()
{
Uri uri(L"http://kennykerr.ca/feed");
SyndicationClient client;
SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);
for (SyndicationItem item : feed.Items())
{
hstring title = item.Title().Text();
printf("%ls\n", title.c_str());
}
}
int main()
{
initialize();
PrintFeedAsync().get();
}
1 ответ
Чтобы функция была сопрограммой, в ее типе возврата должны быть определены определенные черты, описывающие, как будет работать сопрограмма. C++/WinRT определяет эти черты для их версии IAsyncAction
или же IAsyncOperation<TResult>
, В частности, есть два метода, которые обрабатывают возврат из сопрограммы: return_value(...)
или же return_void()
, IAsyncOperation использует первое, а IAsyncAction использует второе.
Глядя на последнюю спецификацию сопрограммы на момент этого ответа, мы находим, что происходит, если в теле функции сопрограммы нет оператора co_return:
Если
p.return_void()
допустимое выражение, вытекающее из конца сопрограммы эквивалентноco_return
без операнда; в противном случае утечка из конца сопрограммы приводит к неопределенному поведению.- "Языки программирования - расширения C++ для сопрограмм" (N4680) § 6.6.3.1/3
Так как C++ / WinRT определяет return_void для признаков IAsyncAction, компилятор будет следовать вышеупомянутому правилу. В конце, где выполнение вытекает из конца сопрограммы, используется метод return_void, так же, как если бы вы завершили функцию с помощью co_return;
, Если мы посмотрим на определение return_void, то увидим, что это эквивалентно установке статуса "Завершено" и вызову обработчика завершения, если он есть.