Re[9]: C++20 coroutines (co_await)
От: night beast СССР  
Дата: 09.01.21 17:26
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Даже библиотечная реализация достаточно юзабельная.

EP>А вот stackless не очень, поэтому если есть выбор лично я предпочту stackless реализацию в стандарте, так как stackful по сути уже доступна.

я бы предпочел иметь их обоих в стандарте, потому как тащить буст только ради них никто не будет
Re[9]: C++20 coroutines (co_await)
От: reversecode google
Дата: 09.01.21 17:45
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, reversecode, Вы писали:


R>>стекфулл корутины очевидно не добавили в стандарт не потому что они легко реализуются самостоятельно

R>>а потому что необходимо будет описать что такое стек(вспоминая Полухина и его бектрейс)
R>>а за этим потянется и расщирения стека и перемещение объектов по стеку не нарушая их состояния, наверняка у комитета от этого взрывался мозг

EP>Перемещение объектов по стэку у stackful корутин врядли кода либо будет, в общем случае это вообще не реализуемо, либо с очень жёсткими ограничениями на вызываемый код, что убьёт всё мощь stackful — ибо они могут работать и прыгать через сторонний код.


при расширении границы стека это неизбежно,
для этого в компиляторах добавили спецхук функцию которую юзает гоуланг
а у него как раз стек динамический и его рост они и проверяют, переаллоцируют память а память может быть ой какой разной и объекты нужно подвинуть

R>>я бы сказал по этому стекфулл корутины не очень юзабельны в С++


EP>Даже библиотечная реализация достаточно юзабельная.

EP>А вот stackless не очень, поэтому если есть выбор лично я предпочту stackless реализацию в стандарте, так как stackful по сути уже доступна.

R>>следить ручками и глазками за размером стека и пытаться сразу же угадать сколько нужно аллоцировать памяти на очередной фрейм это


EP>Ну здесь очевидно непонимание, ибо следить и угадывать размер ручками не нужно и никто не предлагает, даже в макро-реализации stackless из Asio.

EP>Размер фрейма любой функции тривиально известен во время компиляции. Глубина прыжков stackless корутин огранична scope'ом одной фукции, что в C++20, что в C#, что в Python, на то они и stackless. Поэтому и размер корутины, как и её конкретный тип легко может быть известен во время компиляции

я говорил про стекфулл корутины, сколько вы аллоцируете памяти на каждую стекфулл корутину ?
а в бусте ?
а про обработку исключений вы наверное тоже не забыли ?
в том же гоуланг об этом думать не надо, памяти они перераспределят автоматически если стек выростет

короче говоря, стекфулл корутины в С++ нужны как минимум такие как они уже есть в гоуланг
либо они не нужны вообще

в свое время я даже реверснул имплементацию асинхронщины у яндекса о которой они часто рассказывали на докладах,тот же Иван Пузыревский помоему
они там тоже взяли бустовую реализацию
подпилили для большей скорости переключения
окучили исключения
сделали мультифутуры(когда футура может по несколько раз возвщарать значение а не один раз как стандартная)
но даже там стек аллоцируют на глаз
и корутиной сделали саму так сказать футуру в которой стек почти никуда не растет

и хотя в целом имплементация у них "прикольная"
для больших хайлоад на мой взгляд не очень юзабельная

я к чему ? к тому что стекфулл корутины в С++ для поиграться и не больших проектов
  ждем флуда
про то как всякие расспределенны БД юзают стекфулл корутины
Re[10]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 17:47
Оценка:
Здравствуйте, night beast, Вы писали:

EP>>Даже библиотечная реализация достаточно юзабельная.

EP>>А вот stackless не очень, поэтому если есть выбор лично я предпочту stackless реализацию в стандарте, так как stackful по сути уже доступна.

NB>я бы предпочел иметь их обоих в стандарте,


Я согласен — лучше и то и другое, ибо и там и там есть свои сильные и слабые стороны. Например у stackless ограниченна глубина и они нельзя прыгнуть через чужой код, у stackful могут быть проблемы с размером стэка, их не сделать копируемыми/сериализуемыми, более тяжёлые переключения контекста.

NB>потому как тащить буст только ради них никто не будет


Обычно он уже есть. В крайнем случае можно самому напедалить. А вот нормальные stackless увы нет.
Re[10]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 18:06
Оценка:
Здравствуйте, reversecode, Вы писали:

R>>>стекфулл корутины очевидно не добавили в стандарт не потому что они легко реализуются самостоятельно

R>>>а потому что необходимо будет описать что такое стек(вспоминая Полухина и его бектрейс)
R>>>а за этим потянется и расщирения стека и перемещение объектов по стеку не нарушая их состояния, наверняка у комитета от этого взрывался мозг
EP>>Перемещение объектов по стэку у stackful корутин врядли кода либо будет, в общем случае это вообще не реализуемо, либо с очень жёсткими ограничениями на вызываемый код, что убьёт всё мощь stackful — ибо они могут работать и прыгать через сторонний код.
R> при расширении границы стека это неизбежно,

Во-первых перемещать нативный стэк никто не будет, либо будут очень специфичные ограничения на код.
Во-вторых нет, не неизбежно. Адресного пространство под стэк может быть выделенно сразу много, а память аллоцируется по мере необходимости. Либо используются сегментированные стэки.

R>>>следить ручками и глазками за размером стека и пытаться сразу же угадать сколько нужно аллоцировать памяти на очередной фрейм это

EP>>Ну здесь очевидно непонимание, ибо следить и угадывать размер ручками не нужно и никто не предлагает, даже в макро-реализации stackless из Asio.
EP>>Размер фрейма любой функции тривиально известен во время компиляции. Глубина прыжков stackless корутин огранична scope'ом одной фукции, что в C++20, что в C#, что в Python, на то они и stackless. Поэтому и размер корутины, как и её конкретный тип легко может быть известен во время компиляции
R>я говорил про стекфулл корутины, сколько вы аллоцируете памяти на каждую стекфулл корутину ?
R>а в бусте ?

Это параметр. В том числе может быть сегментированный стэк

https://www.boost.org/doc/libs/1_75_0/libs/coroutine2/doc/html/coroutine2/stack/segmented.html
Boost.Coroutine2 supports usage of a segmented_stack, e. g. the size of the stack grows on demand. The coroutine is created with a minimal stack size and will be increased as required


R>а про обработку исключений вы наверное тоже не забыли ?


Обработка исключений для корутин ничем принципиально не отличается от обработки исключений для обычных потоков. Проблема размера стэка тоже присутсвует и там и там, но для потоков менее выраженна в виду меньшего их колличества.

R>в том же гоуланг об этом думать не надо


Ну да, нет исключений, нет проблем — педальте вручную.

R>и хотя в целом имплементация у них "прикольная"

R>для больших хайлоад на мой взгляд не очень юзабельная

R>я к чему ? к тому что стекфулл корутины в С++ для поиграться и не больших проектов


Ты свое мнение сформировал — удачи
Re[11]: C++20 coroutines (co_await)
От: night beast СССР  
Дата: 09.01.21 18:17
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

NB>>потому как тащить буст только ради них никто не будет


EP>Обычно он уже есть. В крайнем случае можно самому напедалить.


платформонезависимо не напедалить
Re[11]: C++20 coroutines (co_await)
От: landerhigh Пират  
Дата: 10.01.21 00:04
Оценка:
Здравствуйте, reversecode, Вы писали:

R> причем здесь стекфул корутины в контексте обсуждаемой имплементации в С++ стеклесс ?


Я упомянул.
Мне все равно не очень понятно, почему стекфул не были предложены в стандарт.

R>вообще все очень притянуто зауши учитывая что я за последние лет 10

R>и стекфул корутин не наблюдал в любом маломайски популярном или топ нейм продукте на С или С++

Одна из ведущих SCADA систем, установленная в 80% датацентров и еще черт знает где, имеет в себе модули с корутинами на boost::context (boost::coroutine еще не было)
www.blinnov.com
Re[3]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 10.01.21 04:29
Оценка:
EP>Подскажи пожалуйста, они дали возможность сохранить корутину через её конкретный тип, или там до сих пор есть стирание типа вытекающие в аллокацию (которое было в ранних вариантах)?

Походу стирание конкретного типа и аллокацию таки оставили:

https://en.cppreference.com/w/cpp/language/coroutines
Each coroutine is associated with
* the coroutine state, which is an internal, heap-allocated (unless the allocation is optimized out)

спасибо майкрософт за это
Re[2]: C++20 coroutines (co_await)
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 10.01.21 05:09
Оценка:
Здравствуйте, student__, Вы писали:

__>Так это новый виток в эре копроэкономики наступил

Либо ты просто не понимаешь что там написано из-за отсутствия нужных знаний.
Sic luceat lux!
Re[5]: C++20 coroutines (co_await)
От: х Россия  
Дата: 10.01.21 07:20
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Вопрос не про типизацацию в плане безопасности, а про стирание типа, type erasure. Ибо я именно что стирание типа и наблюдаю — std::coroutine_handle, каковым оно и было в ранних версиях.


а чем плох type erasure в данном случае? Насколько я понял, конкретный тип лежит в параметре шаблона U и можно попробовать его анализировать. Но зачем? Можно пример?

EP>Если разные генераторы, с разным набором и колличеством локальных переменных можно сохранить в один и тот же тип — то это и есть стирание типов, которого по-хорошему быть не должно. То есть оно может быть опциональным, по-желанию, как и std::function для замыканий, но не долнжо быть единственным вариантом.


Если Вы про то что так трудно контролировать время жизни конкретного аргумента, то соглашусь. Можете привести другие примеры почему в данном случае "стирание типов ... быть не должно"?
С уважением Вадим.
Re[4]: C++20 coroutines (co_await)
От: х Россия  
Дата: 10.01.21 07:49
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Походу стирание конкретного типа и аллокацию таки оставили:

EP>

EP>https://en.cppreference.com/w/cpp/language/coroutines
EP>Each coroutine is associated with
EP>* the coroutine state, which is an internal, heap-allocated (unless the allocation is optimized out)

EP>спасибо майкрософт за это

Там можно new перекрыть в promise, чтобы оптимизировать аллокаторы.
С уважением Вадим.
Re[10]: C++20 coroutines (co_await)
От: landerhigh Пират  
Дата: 10.01.21 09:53
Оценка:
Здравствуйте, reversecode, Вы писали:

R>я к чему ? к тому что стекфулл корутины в С++ для поиграться и не больших проектов


Мы использовали.
Правда, пришлось прикинуть размер стека на пальцах. Оказалось, что в нашем случае 64 килобайта хватит за глаза и уши.

Но в процессе разработки выяснили, что MS опять кое-что не совсем полностью документировали и при интеропе CLR->C++->boost::context->CLR CLR выдавал ошибку out of memory.
Удалось пофиксить в boost::context
www.blinnov.com
Re[5]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 10.01.21 10:24
Оценка: +1
Здравствуйте, х, Вы писали:

х>Там можно new перекрыть в promise, чтобы оптимизировать аллокаторы.


А можно было бы вообще обойтись без аллокации, так же как и для обычных лямбд/замыканий.
И потом, даже если делать in-place аллокатор для небольших корутин — то скроей всего будет либо перерасход памяти, либо таки аллокация в куче.
Re[6]: C++20 coroutines (co_await)
От: х Россия  
Дата: 10.01.21 10:31
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, х, Вы писали:


х>>Там можно new перекрыть в promise, чтобы оптимизировать аллокаторы.


EP>А можно было бы вообще обойтись без аллокации, так же как и для обычных лямбд/замыканий.


Да, тут согласен.

EP>И потом, даже если делать in-place аллокатор для небольших корутин — то скроей всего будет либо перерасход памяти, либо таки аллокация в куче.

Можно выделать прямо в promise. Если код наш, то ограничить размер фрейма не большая проблема. Может в следующих версиях поправят.
С уважением Вадим.
Re[6]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 10.01.21 10:39
Оценка: +1
Здравствуйте, х, Вы писали:

EP>>Вопрос не про типизацацию в плане безопасности, а про стирание типа, type erasure. Ибо я именно что стирание типа и наблюдаю — std::coroutine_handle, каковым оно и было в ранних версиях.

х>а чем плох type erasure в данном случае? Насколько я понял, конкретный тип лежит в параметре шаблона U и можно попробовать его анализировать.

Там конкретный тип promise, а не конкретной корутины. Разные корутины выдающие один и тот же promise, могут иметь разный размер, так как имеют разный размер фрейма.

х>Но зачем? Можно пример?


Представь что если бы у обычного замыкания, не было конкретного типа, а всегда был тип std::function
std::function<void()> type_erased_labmda = [=]{ ... };

И все замыкания, независимо от размера их контекста, всегда бы имели один и тот же тип.
Это привело бы к неменуемым аллокациям (разные замыканиия имеют разный контекст, и соответсвенно разный размер, и поэтому все не могут быть сохранены целиком в один и тот же тип sizeof которого фиксирован), и проблемам с оптимизацией. Вот в случае с сабжем, мы именно это и получили

EP>>Если разные генераторы, с разным набором и колличеством локальных переменных можно сохранить в один и тот же тип — то это и есть стирание типов, которого по-хорошему быть не должно. То есть оно может быть опциональным, по-желанию, как и std::function для замыканий, но не долнжо быть единственным вариантом.

х>Если Вы про то что так трудно контролировать время жизни конкретного аргумента, то соглашусь. Можете привести другие примеры почему в данном случае "стирание типов ... быть не должно"?

Проблемы с контролем времени жизни нет, даже при стирании типа — тот же std::function имеет вполне нормальное время жизни.
Проблема есть с тем что мы не можем целиком сохранить целиком корутину в поле объекта. Проблема в том что при комбинировании корутин с алгортимами, даже если алгоритм шаблонный — то будет проблема с оптимизацией, так как для всех генераторов будет выводится один и тот же тип, и оптимизации без инлайнинга вообще не будет (которая есть в нормальных случаях, ибо шаблон инстанцируется под конкретный объект).
Когда я использую генераторы (например генератор выпрявляющий vector<vector<int>> в один range из int'ов), я хочу чтобы результат по скорости не отличался от вручную оптимизированного — zero-overhead — тоже самое что мы уже имеем с замыканиями, с сабжем так не получися, увы.
Re[7]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 10.01.21 10:46
Оценка:
Здравствуйте, х, Вы писали:

EP>>И потом, даже если делать in-place аллокатор для небольших корутин — то скроей всего будет либо перерасход памяти, либо таки аллокация в куче.

х>Можно выделать прямо в promise. Если код наш, то ограничить размер фрейма не большая проблема.

Проблема не только с размером, но и с оптимизацией как таковой. Не зная конкретного типа, в общем случае мы всегда обреченны делать runtime dispatch, так как это делает std::function. Более того, мы не можем заинлайнить весь генератор в вызывающий код в общем случае, особенно если этот генератор пришёл из вне.

х>Может в следующих версиях поправят.


Это не исправлять надо (к сожалению маловероятно что это произойдёт), а сразу надо было делать правильно, и уже были предложения как именно можно сделать оптимально. И были возражения по текущей версии, и авторам приходелось отбрехиваться мол компилятор соптимизирует аллокацию.
Отредактировано 10.01.2021 10:47 Evgeny.Panasyuk . Предыдущая версия .
Re[8]: C++20 coroutines (co_await)
От: reversecode google
Дата: 10.01.21 18:38
Оценка:
пардон, но смотря на то уродсто(пропозл) от автора асио
даже растоманы бы имели полное право плевать на С++

если сравнить то уродство с классным 6 колесным велосипедом с турбо наддувом
то ту имплементацию что добавил микрософт можно сравнить разве что с межгалактическим кораблем
до которого даже имплементации генераторов раста далеко
Re[7]: C++20 coroutines (co_await)
От: х Россия  
Дата: 11.01.21 15:10
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, х, Вы писали:


EP>Там конкретный тип promise, а не конкретной корутины. Разные корутины выдающие один и тот же promise, могут иметь разный размер, так как имеют разный размер фрейма.


size_t окружения передаётся в new.

EP>Представь что если бы у обычного замыкания, не было конкретного типа, а всегда был тип std::function

EP>
EP>std::function<void()> type_erased_labmda = [=]{ ... };
EP>

EP>И все замыкания, независимо от размера их контекста, всегда бы имели один и тот же тип.
EP>Это привело бы к неменуемым аллокациям (разные замыканиия имеют разный контекст, и соответсвенно разный размер, и поэтому все не могут быть сохранены целиком в один и тот же тип sizeof которого фиксирован), и проблемам с оптимизацией. Вот в случае с сабжем, мы именно это и получили

Витиевато ты как-то пишешь. Лучше бы не основы писал, а что предлагаешь, было бы понятнее.

EP>Проблемы с контролем времени жизни нет, даже при стирании типа — тот же std::function имеет вполне нормальное время жизни.


В корутинах есть. Ладно, сейчас не об этом.

EP>Проблема есть с тем что мы не можем целиком сохранить целиком корутину в поле объекта. Проблема в том что при комбинировании корутин с алгортимами, даже если алгоритм шаблонный — то будет проблема с оптимизацией, так как для всех генераторов будет выводится один и тот же тип, и оптимизации без инлайнинга вообще не будет (которая есть в нормальных случаях, ибо шаблон инстанцируется под конкретный объект).

EP>Когда я использую генераторы (например генератор выпрявляющий vector<vector<int>> в один range из int'ов), я хочу чтобы результат по скорости не отличался от вручную оптимизированного — zero-overhead — тоже самое что мы уже имеем с замыканиями, с сабжем так не получися, увы.

В общем по мне ты сложно как-то пишешь. Попробую моими словами. Проблемы две: 1. вынужденный new, который идёт как следствие того, что надо в фиксированный размер запихнуть нефиксированный локальный фрейм. Вторая проблема, что нельзя включить шаблонную оптимизацию.

Давай обсуждать какие есть варианты для решения.

Допустим замена:
template<typename U>
    void await_suspend(std::experimental::coroutine_handle<U> hndl) noexcept {
      this->_future.then([hndl]() mutable {
        hndl();
      });

на
template<typename U, typename... Locals>
    void await_suspend(U hndl, Locals args...) noexcept {
      this->_future.then(hndl, std::forward<Locals>(args));

то что хочется?

В общем какое предложение?
С уважением Вадим.
Re[8]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 16.01.21 06:30
Оценка:
Здравствуйте, х, Вы писали:

EP>>Там конкретный тип promise, а не конкретной корутины. Разные корутины выдающие один и тот же promise, могут иметь разный размер, так как имеют разный размер фрейма.

х>size_t окружения передаётся в new.

Ага, в рантайме, отсюда и неизбежная аллокация в общем случае.

х>В общем по мне ты сложно как-то пишешь. Попробую моими словами. Проблемы две: 1. вынужденный new, который идёт как следствие того, что надо в фиксированный размер запихнуть нефиксированный локальный фрейм. Вторая проблема, что нельзя включить шаблонную оптимизацию.


Ну ещё проблема в том, что за счёт стирания типов, мы внезапно теряем информацию о типах, что снижает общую типизацию, и возможности по перегрузке/специализации после того как корутина уже создана.

х>Давай обсуждать какие есть варианты для решения.

х>Допустим замена:
х>
х>template<typename U, typename... Locals>
х>    void await_suspend(U hndl, Locals args...) noexcept {
      this->>_future.then(hndl, std::forward<Locals>(args));
х>

х>то что хочется?
х>В общем какое предложение?

Что-то типа, и в таком исполнении тип _future дожен зависить от конкретной корутины.

Если в общем, то например хочется чтобы вместо:
template<typename R, typename... Args> struct coroutine_traits;
Было:
template<typename ConcreteCoroutine, typename R, typename... Args> struct coroutine_traits;
Где соответвенно тип ConcreteCoroutine будет разным для:
generator<int> iota(int n);
и для
generator<int> even(int n);
Несмотря на то что у них одинаковые типы параметров и результата, потому что их локальные переменные И код могут быть разным.

Если же потребуется type-erasure (которое является нормальной техникой, у того же std::function есть вполне реальные и обоснованные варианты применения, с этим никто не спорит), то вложенные типы (::promise_type) coroutine_traits будут не зависеть от типа ConcreteCoroutine, либо зависеть но как-то выборочно (например все корутины размером до 32 байт будут давать один тип, все остальные другой, то есть тип стирается но "частично").

Но это о том как поправить вот эту вот реализацию. А принципиально проблемы нет, так как это УЖЕ работает на макросах, и вполне понятно как сделать механическую трансформацию кода из описания корутины в класс конкретного типа, собественно макросы и помогают делать эту трансформацию, конечно в меру своих ограниченных возможностей.
Отредактировано 16.01.2021 6:33 Evgeny.Panasyuk . Предыдущая версия .
Re[9]: C++20 coroutines (co_await)
От: х Россия  
Дата: 16.01.21 10:38
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Ага, в рантайме, отсюда и неизбежная аллокация в общем случае.


Как минимум хотя бы одна аллокация нужна же (см. дальше).

х>>Давай обсуждать какие есть варианты для решения.

х>>Допустим замена:
х>>
х>>template<typename U, typename... Locals>
х>>    void await_suspend(U hndl, Locals args...) noexcept {
      this->>>_future.then(hndl, std::forward<Locals>(args));
х>>

х>>то что хочется?
х>>В общем какое предложение?

EP>Что-то типа, и в таком исполнении тип _future дожен зависить от конкретной корутины.


EP>Если в общем, то например хочется чтобы вместо:

EP>
EP>template<typename R, typename... Args> struct coroutine_traits;
EP>
Было:

EP>
EP>template<typename ConcreteCoroutine, typename R, typename... Args> struct coroutine_traits;
EP>
Где соответвенно тип ConcreteCoroutine будет разным для:

EP>
EP>generator<int> iota(int n);
EP>
и для

EP>
EP>generator<int> even(int n);
EP>
Несмотря на то что у них одинаковые типы параметров и результата, потому что их локальные переменные И код могут быть разным.


Хорошо, но где хранить разность (их локальные переменные)? После вызова этой функции у нас есть только generator<int>, а значит состояние самой функции где-то лежать должно. Пусть даже в упаковке для лямбды. Если ты согласен, что как минимум один new на heap нужен, то дальше можно проскипать — согласен. Но если ты можешь сказать как вообще избавиться от new — с удовольствием прочту идею.

EP>Если же потребуется type-erasure (которое является нормальной техникой, у того же std::function есть вполне реальные и обоснованные варианты применения, с этим никто не спорит), то вложенные типы (::promise_type) coroutine_traits будут не зависеть от типа ConcreteCoroutine, либо зависеть но как-то выборочно (например все корутины размером до 32 байт будут давать один тип, все остальные другой, то есть тип стирается но "частично").


Ну то есть один new для лабды ты допускаешь?
С уважением Вадим.
Re[10]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 16.01.21 17:05
Оценка:
Здравствуйте, х, Вы писали:

EP>>template<typename ConcreteCoroutine, typename R, typename... Args> struct coroutine_traits;

EP>>[/ccode]Где соответвенно тип ConcreteCoroutine будет разным для:
EP>>
EP>>generator<int> iota(int n);
EP>>
и для

EP>>
EP>>generator<int> even(int n);
EP>>
Несмотря на то что у них одинаковые типы параметров и результата, потому что их локальные переменные И код могут быть разным.

х>Хорошо, но где хранить разность (их локальные переменные)? После вызова этой функции у нас есть только generator<int>

Нет, вот тут не верно.
После вызова, у нас объект типа который определяется через corountine_traits<ConcreteCoroutine, generator<int>, int>. И этот тип может зависеть от ConcreteCoroutine, а может не зависеть — по желанию автора специализации.

х>Если ты согласен, что как минимум один new на heap нужен, то дальше можно проскипать — согласен.


Не согласен.

х>Но если ты можешь сказать как вообще избавиться от new — с удовольствием прочту идею.


Абстрагируйся от await'а, рассмотрим генератор:
generator<int> three()
{
    co_yield 1;
    co_yield 2;
    co_yield 3;
}

Возьмём простой интерфейс:
for(auto g=three(); g;)
    print(g());

Сможешь написать реализацию three вручную, удовлетворяющую этому интерфейсу и такую что программа напечатает "1\n2\n3\n"?
А без аллокаций?
А без аллокаций и без надежы на heap allocation elision optimization?

EP>>Если же потребуется type-erasure (которое является нормальной техникой, у того же std::function есть вполне реальные и обоснованные варианты применения, с этим никто не спорит), то вложенные типы (::promise_type) coroutine_traits будут не зависеть от типа ConcreteCoroutine, либо зависеть но как-то выборочно (например все корутины размером до 32 байт будут давать один тип, все остальные другой, то есть тип стирается но "частично").

х>Ну то есть один new для лабды ты допускаешь?

Я говорю что type-erasure можно получить если этого захочется из конкретного типа. Также как и можно получить std::function из конкретной лямбды.
А вот если тип уже стёрт, то обратный фокус уже не получится проделать.
Отредактировано 16.01.2021 17:06 Evgeny.Panasyuk . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.