为何基于无界iota的take_view不满足sized_range要求?
为什么无界std::views::iota结合take_view后无法调用size()?
先看两段代码的对比:
可正常编译的代码(有界iota)
#include <ranges> #include <iostream> int main() { auto int_view = std::views::iota(0, 20) | std::views::take(15); std::cout << int_view.size() << std::endl; // 输出15 return 0; }
编译失败的代码(无界iota)
#include <ranges> #include <iostream> int main() { auto int_view = std::views::iota(0) | std::views::take(15); std::cout << int_view.size() << std::endl; // 编译报错:size()成员不存在 return 0; }
核心原因
C++标准对std::ranges::take_view的size()成员函数的设计逻辑是:返回底层范围的大小与指定的take数量两者中的较小值。这就要求底层范围必须是sized_range(即支持在常量时间内返回自身大小的范围),否则take_view不会拥有合法的size()成员。
你可能会疑惑:既然已经明确要取15个元素,那take_view的大小理应为15,为什么还要依赖底层范围的size?但实际上,take_view是通用的范围适配器,标准并没有为“无界范围+固定数量take”的场景单独做特殊特化。它的设计保持了通用性,只在底层范围本身是sized_range时,才会让take_view也成为sized_range。
解决办法
如果只是需要这个视图的大小,你已经知道take的数量是15,直接使用这个数值即可;如果确实需要通过视图的size()成员获取,你可以将其转换为一个支持size的容器或视图(比如std::ranges::to<std::vector>(),但这会复制元素,仅在必要时使用)。
内容的提问来源于stack exchange,提问作者Reimundo Heluani
相关产品推荐
相关产品推荐

