为何C++中左值std::generator无法使用std::views::zip?
关于std::generator作为左值无法用于std::views::zip的问题
先看这段可正常编译运行的代码:
std::generator<int> get_ints(int n) { for (int i{0}; i < n; ++i) co_yield i; } int main(int argc, char* argv[]) { std::vector<float> floats { 0.0f, 1.0f, 2.0f, 3.0f }; for (auto [i, f] : std::views::zip(get_ints(4), floats)) std::println("{}: {}", i, f); }
但如果把生成器存入变量再使用,就会编译失败:
std::generator<int> get_ints(int n) { for (int i{0}; i < n; ++i) co_yield i; } int main(int argc, char* argv[]) { std::vector<float> floats { 0.0f, 1.0f, 2.0f, 3.0f }; auto ints = get_ints(4); for (auto [i, f] : std::views::zip(ints, floats)) std::println("{}: {}", i, f); }
编译失败的核心原因是std::ranges::viewable_range<std::generator<int>&>的判定结果为false,而右值引用版本std::ranges::viewable_range<std::generator<int>&&>为true。
为什么左值情况被禁止?
std::generator是单次迭代的范围:它的迭代过程会消耗自身状态,一旦迭代完成,生成器就无法再产生新的值,多次迭代会导致未定义行为(比如直接返回空序列)。- 标准库刻意限制左值生成器的
viewable_range,是为了避免用户误操作——左值变量可以被多次使用,如果允许左值生成器参与视图组合,很容易出现“重复迭代同一个生成器”的错误,而这种错误的行为很难排查。 - 像
std::vector这类常规范围是多趟迭代安全的,左值引用可以被反复迭代而不会出现问题,所以它们的左值引用能满足viewable_range约束。
解决方法
如果一定要用左值变量的生成器,可以显式用std::move将其转为右值,明确告知编译器这个生成器只会被使用一次:
std::generator<int> get_ints(int n) { for (int i{0}; i < n; ++i) co_yield i; } int main(int argc, char* argv[]) { std::vector<float> floats { 0.0f, 1.0f, 2.0f, 3.0f }; auto ints = get_ints(4); // 使用std::move转换为右值 for (auto [i, f] : std::views::zip(std::move(ints), floats)) std::println("{}: {}", i, f); }
内容的提问来源于stack exchange,提问作者Carsten
相关产品推荐
相关产品推荐

