Сопрограмма return_void; разница между co_return; и падаю с конца

На cppreference я прочитал следующее (выделено мной):

Выход за конец сопрограммы эквивалентен co_return;, за исключением того, что поведение не определено, если в области видимости Promise не найдено ни одного объявления return_void.

Но clang 18.1.0 ведет себя по-другому в отношении уничтожения локальных переменных. Когда я падаю с конца сопрограммы, локальные переменные разрушаются, а затем вызывается return_value. Когда я использую co_return;, return_value вызывается перед уничтожением локальных переменных.

Мой вопрос: делает ли cppreference более сильное заявление о co_return; против падения, чем фактический стандарт? Является ли поведение лязгов ошибкой или соответствует стандарту?

Вот небольшой образец, показывающий разницу, а также крестик для вашего удобства:

#include <iostream>
#include <coroutine>

struct Coroutine {
    struct promise_type {
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }

        Coroutine get_return_object() { return {}; }

        void unhandled_exception(){}
        void return_void() {
            std::cout << "return_void called\n";
        }
    };
};

struct LogOnDestruct {
    ~LogOnDestruct() {
        std::cout << "Destructed\n";
    }
};

Coroutine foo() {
    LogOnDestruct logger{};
    co_await std::suspend_never{};
}
Coroutine bar() {
    LogOnDestruct logger{};
    co_return;
}

int main() {
    foo();
    bar();

    return 0;
}
godbolt.org/z/j75xjTf5P — это ваш код, отпечатки которого ясно показывают, откуда они берутся.
Yakk - Adam Nevraumont 16.07.2024 16:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
1
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Стандарт довольно ясен:

Если p.return_void() является допустимым выражением, выход из конца сопрограммы эквивалентен co_return без операнда; в противном случае выход за пределы сопрограммы приведет к неопределенному поведению.

Структура сопрограммы такова, что определяемое вами тело функции фактически находится внутри области действия более крупной функции, поэтому все локальные переменные этой функции находятся в этой области. Таким образом, co_return выходит из этой области, как если бы это был оператор goto. Но это происходит только после вызова соответствующей функции обещания. Таким образом, обещание должно получить вызов функции до того, как будут уничтожены любые локальные переменные.

Я правильно понимаю, что это будет дефектом реализации clangs? (например: правильное поведение — это явное поведение co_return;, поведение спада — это дефект лязга)

Wutz 16.07.2024 21:20

@wutz Ну, co_return expr; должно произойти до того, как локальные переменные будут уничтожены (я думаю: в противном случае висящие вещи в expr очень опасны), поэтому co_return; должно имитировать это, а бездействие должно имитировать co_return;.

Yakk - Adam Nevraumont 17.07.2024 20:43

Другие вопросы по теме