如何在干净的代码中向后移动双向迭代器?

时间:2017-09-27 22:47:07

标签: c++ c++11 containers

假设我有一个std :: map并希望对带有键X的项目和带有更高键的每个项目执行某些操作(请记住,这是一个有序的映射)。代码清晰明了:

auto iter = mymap.find(X);
while (iter != mymap.end()) {
    process(*iter);
    iter++;
}

或者,可能更好,std::for_each(mymap.find(X), mymap.end(), process)

但是,如果我的任务是使用键X对项目进行处理,并使用 lower 键对每个项目执行处理,按此顺序,我找不到表达意图的干净编码模式

auto iter mymap.find(x);
if (iter != mymap.end()) {
    iter++;                           // Go forward...
    while (iter != mymap.begin()) {
        iter--;                       // ... so we can go backwards
        process(*iter);
    }
}

如果我不想以相反的顺序执行它们,那么增加std :: map :: find()返回的迭代器然后使用std :: for_each(mymap.begin( ),incremented_iter,process)。

双向迭代器不会反转迭代器,所以我不能使用mymap.rend()作为开头的#34;"在while()循环中进行比较。

在C ++ 11中是否有一种干净的方法(或者在+14或+17中,所以我会有一些值得期待的东西)?

1 个答案:

答案 0 :(得分:2)

您希望使用键或更低处理每个项目,并使用键X从元素开始处理,然后返回。您可以做的是在第一个元素过去键X上使用reverse_iterator并创建一个反向迭代器,它指向之前的元素 。然后你可以迭代直到"反向结束":

auto pastX = mymap.upper_bound(X); // First element with key > X
// make_reverse_iterator returns iter that dereferences to the previous element
for (auto iter = std::make_reverse_iterator(pastX); iter != mymap.rend(); ++iter)
    // Use *iter

为了更好的可读性,我通常会保留一些辅助函数来创建一个"可迭代对象" (可以用.begin().end()调用一个迭代器中的一个,所以我实际上会写:

auto pastX = mymap.upper_bound(X);
// "IteRange" would return a "range-for-iterable" object from two iterators
for (auto&& elem : IteRange(std::make_reverse_iterator(pastX), mymap.rend()))
    // Use elem