我正在尝试使用Boost.Range处理输入序列。这个库有很多不足之处,所以我必须自己编写一些额外的范围适配器。他们中的大多数都很简单,但是当我尝试实现相当于Haskell的groupBy(或range-v3的group_by_view)时遇到了一些困难。它是一个转换,它接受一个输入范围并返回一系列范围,每个范围包含一个来自输入的相邻元素序列,它们满足某个给定的二元谓词。例如,如果二元谓词只是std::equal_to<int>()
,那么序列
{1, 1, 2, 3, 5, 5, 5, 4, 1}
将映射到
{{1, 1}, {2}, {3}, {5, 5, 5}, {4}, {1}}
我的问题是这个适配器的接口。假设
auto i = (input | grouped_by(std::equal_to<int>())).begin();
如果i
递增,则必须扫描基础序列,直到找到2.但是,如果我首先扫描*i
(范围{1, 1}
),我基本上已经找到第一组的结尾,因此由++i
引起的遍历将是多余的。有可能从内部迭代器到外部迭代器有一些反馈路径,即让i
从内部迭代器到达的最后一个元素开始扫描,但这会导致很多开销,并且冒着创建悬空迭代器的风险
我想知道是否有一些惯用的方法来处理这个问题。理想情况下,重新定义grouped_by
接口可以完全回避问题。显然,必须扫描输入范围以找到每个组的开头,但我希望有一个强大的方法来做到这一点,而无需重新扫描元素。 (通过鲁棒,我的意思是,只要基础输入范围的迭代器有效,并且当然不在扫描本身期间就不会使迭代器无效。)
那么..有没有一些已知/已证实/优雅的解决方案呢?