C++20中将多个范围适配器串联为单个范围的方法

7

考虑以下情况:

std::vector<int> v{0, 1, 2, 3, 4, 5};
// 0 1 2 3 4 5
auto rng1 = std::views::all(v);
// 5 4 3 2 1 0
auto rng2 = std::views::reverse(v);
// 4 2 0
auto rng3 = std::views::filter(rng2, [](int x){return x % 2 == 0;});

有没有一种优雅的方法将这三个适配器连接成一个单一的视图,就像这样:
// 0 1 2 3 4 5 5 4 3 2 1 0 4 2 0
auto final_rng = std::views::concat(rng1, rng2, rng3);

由于rng1rng2rng3的类型非常不同,因此似乎是不可能的。

有人能提供另一种解决方案吗?谢谢。


当然是可能的。我在标准库中找不到它,但这将是 my_concat<rng1 的类型, rng2 的类型, rng3 的类型>,其迭代器基本上是一个 variant<rng1::iter, rng2::iter, rng3::iter> - Justin
2个回答

4

是的,你所写的代码只是在不同的命名空间中 - 标准库中没有concat函数,但在range-v3中有一个:

auto final_rng = ranges::views::concat(rng1, rng2, rng3);

范围不同类型并不是问题。你只需构建一个由范围基础迭代器的变种组成的迭代器即可。重要的是范围的值类型相同,而在这里它是相同的,所以完全没问题。


1
为什么它不在std范围内呢? - Pirulax
可能只是时间限制。我预计根据它们支持的访问/迭代类型,不同范围的连接可能会变得非常复杂。实现一个工作版本与正式正确的定义相当不同,后者可以实现高性能。 - Ramon
2
我在标准的C++20和C++23中都没有看到views::concat()。这是一个重要的缺失功能还是有其他简单的方法可以实现? - Ludovic Aubert
看起来这是计划在C++26中实施的 https://github.com/cplusplus/papers/issues/1204 - oblivioncth
看起来这个计划是为C++26准备的。https://github.com/cplusplus/papers/issues/1204 - undefined

3

1
很高兴看到有计划添加它。值得注意的是,目前的C++23草案(N4928)尚未包含concat(如果存在,它将是26.6中的一种范围工厂)。 - ReinstateMonica3167040

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接