但即使我们什么都不用 e,这个公式很方便,也更难出错。另一种方式(检查变化的值)更乏味(因为我们需要特别处理最后一个范围[...])
取决于您如何解释“特别处理最后一个范围”:
auto begin = v.begin();
// we might need some initialization for whatever on *begin...
for(Iterator i = begin + 1; ; ++i)
{
if(i == v.end() || *i != *begin)
{
// handle range single element of range [begin, ???);
if(i == v.end())
break;
begin = i;
// re-initialize next range
}
}
最后一个范围没有特殊处理 - 只是,可能需要两次初始化代码......
嵌套循环方法:
auto begin = v.begin();
for(;;)
{
// initialize first/next range using *begin
for(Iterator i = begin + 1; ; ++i)
{
if(i == v.end() || *i != *begin)
{
// handle range single element of range [begin, ???);
if(i == v.end())
goto LOOP_EXIT;
begin = i;
break;
}
}
}
LOOP_EXIT:
// go on
// if nothing left to do in function, we might prefer returning over going to...
更优雅?承认,我自己也很怀疑……不过,这两种方法都避免在同一范围内迭代两次(首先是为了找到终点,然后是实际的迭代)。如果我们从以下位置创建自己的库函数:
template <typename Iterator, typename RangeInitializer, typename ElementHandler>
void iterateOverEqualRanges
(
Iterator begin, Iterator end,
RangeInitializer ri, ElementHandler eh
)
{
// the one of the two approaches you like better
// or your own variation of...
}
然后我们可以像这样使用它:
std::vector<...> v;
iterateOverEqualRanges
(
v.begin(), v.end(),
[] (auto begin) { /* ... */ },
[] (auto current) { /* ... */ }
);
现在终于,它看起来类似于 eg std::for_each
,不是吗?