В range-v3, просмотр только для перемещения в порядке. Это было реализовано поздно, и все еще могут быть ошибки, но это не то, что здесь происходит.
Первая проблема заключается в том, что вы пытаетесь адаптировать lvalue типа cppcoro::generator
здесь:
auto rng = gen();
for (auto n : rng | ranges::view::join) {
Поскольку генератор является представлением, представление join
захочет скопировать его. Не может, потому что не копируется.
Вы можете решить эту проблему, переместив генератор в:
auto rng = gen();
for (auto n : std::move(rng) | ranges::view::join) {
Затем вы сталкиваетесь со следующей проблемой, которая заключается в том, что ссылочный тип generator<generator<int>>
равен const generator<int>&
, и у вас снова возникает та же проблема: join
хочет хранить копию внутреннего генератора, пока он выполняет итерации. над ним, но он не может сделать копию.
Обходной путь немного уродлив: измените генератор, чтобы он возвращал неконстантную ссылку на lvalue:
cppcoro::generator<cppcoro::generator<int>&> gen() {
for (int n = 1; n < 100; n += 10) {
auto tmp = gen_impl(n);
co_yield tmp;
}
}
, а затем std::move
каждый внутренний диапазон с представлением move
:
auto rng = gen();
for (auto n : std::move(rng) | ranges::view::move | ranges::view::join) {
std::cout << n << '\n';
}
Результат компилируется. Работает ли он или нет, зависит от того, насколько изящно cppcoro обрабатывает случай, когда кто-то крадет уйму ценности, которую он безопасно спрятал в типе обещания сопрограммы.
https://godbolt.org/z/mszidX
Записка о будущем std::view::join
:
Представление join
, которое будет поставляться с C ++ 20, немного отличается. Если тип ссылки внешнего диапазона является реальной ссылкой (как в этом случае), он не будет пытаться сделать копию представления, на которое он ссылается. Это означает, что в C ++ 20 вам не понадобится уродливый view::move
хак.
Однако концепция C ++ 20 View
в настоящее время требует копирования, поэтому это решение по-прежнему не будет работать. У нас есть пункт TODO, чтобы смягчить это до выхода C ++ 20, но пока неизвестно, как Комитету понравится эта идея.