我正在尝试学习 C++ 范围。据我所知,创建生成自定义序列的范围视图对象的最简单(也是唯一的,除了实现自定义范围视图类)方法是使用 C++23' std::generator<>
:
std::generator<char> letters_gen(char start)
{
for (;;) co_yield start++;
}
如何在涉及范围操作的多个表达式中使用std::generator
对象(通过调用创建letters_gen()
)?例如,如果我想将 10 个字母收集到一个向量中,然后将另外 15 个字母收集到另一个向量中:
int main()
{
auto letters = letters_gen('a');
auto x = letters | std::views::take(10) | std::ranges::to<std::vector>();
auto y = letters | std::views::take(15) | std::ranges::to<std::vector>();
}
这不能编译:
main.cc:150:26: error: no match for ‘operator|’ (operand types are ‘std::generator<char>’ and ‘std::ranges::views::__adaptor::_Partial<std::ranges::views::_Take, int>’)
如果有的话,什么是正确的方法可以达到预期的效果?
你不知道。
A
generator
是输入范围,您只能使用它一次。库寻求防止滥用的方法之一是使其只移动而不是可复制 - 因此有人抱怨尝试复制它(范围编译错误是出了名的无用)。甚至对范围调用两次都是未定义的行为begin()
。我认为在库中没有真正好的方法来做到这一点。您可以尝试通过执行以下操作来解决复制问题(这还可以确保两种算法使用相同的生成器):
这是未定义的行为,但即使将其放在一边,也会给您令人惊讶的结果,即包含所需的从thru开始
x
的字母,但由于与输入范围交互的方式,包含thru而不是thru (参见我的 CppNow 演讲)。a
j
y
l
z
k
y
take
你必须手写更多内容:
对于 Barry 的出色回答,我想补充以下内容。并非所有事情都如此悲观。是的,在这种情况下我们将无法使用视图,但我们可以使用算法 - std::copy_n 和 std::ranges::copy_n:
或者: