Сообщение Re[10]: C++20 coroutines (co_await) от 16.01.2021 17:05
Изменено 16.01.2021 17:06 Evgeny.Panasyuk
Re[10]: C++20 coroutines (co_await)
Здравствуйте, х, Вы писали:
EP>>template<typename ConcreteCoroutine, typename R, typename... Args> struct coroutine_traits;
EP>>[/ccode]Где соответвенно тип ConcreteCoroutine будет разным для:
EP>>
EP>>
х>Хорошо, но где хранить разность (их локальные переменные)? После вызова этой функции у нас есть только generator<int>
Нет, вот тут не верно.
После вызова, у нас объект типа который определяется через corountine_traits<ConcreteCoroutine, generator<int>, int>. И этот тип может зависить от ConcreteCoroutine, а может не зависить — по желанию автора специализации.
х>Если ты согласен, что как минимум один new на heap нужен, то дальше можно проскипать — согласен.
Не согласен.
х>Но если ты можешь сказать как вообще избавиться от new — с удовольствием прочту идею.
Абстрагируйся от await'а, рассмотрим генератор:
Возьмём простой интерфейс:
Сможешь написать реализацию 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 из конкретной лямбды.
А вот если тип уже стёрт, то обратный фокус уже не получится проделать.
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 из конкретной лямбды.
А вот если тип уже стёрт, то обратный фокус уже не получится проделать.
Re[10]: C++20 coroutines (co_await)
Здравствуйте, х, Вы писали:
EP>>template<typename ConcreteCoroutine, typename R, typename... Args> struct coroutine_traits;
EP>>[/ccode]Где соответвенно тип ConcreteCoroutine будет разным для:
EP>>
EP>>
х>Хорошо, но где хранить разность (их локальные переменные)? После вызова этой функции у нас есть только generator<int>
Нет, вот тут не верно.
После вызова, у нас объект типа который определяется через corountine_traits<ConcreteCoroutine, generator<int>, int>. И этот тип может зависеть от ConcreteCoroutine, а может не зависеть — по желанию автора специализации.
х>Если ты согласен, что как минимум один new на heap нужен, то дальше можно проскипать — согласен.
Не согласен.
х>Но если ты можешь сказать как вообще избавиться от new — с удовольствием прочту идею.
Абстрагируйся от await'а, рассмотрим генератор:
Возьмём простой интерфейс:
Сможешь написать реализацию 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 из конкретной лямбды.
А вот если тип уже стёрт, то обратный фокус уже не получится проделать.
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 из конкретной лямбды.
А вот если тип уже стёрт, то обратный фокус уже не получится проделать.