2017-09-27 60 views
0

假設我有一個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對每個項目執行處理,並按下一個鍵的順序,我找不到表示意圖的乾淨編碼模式。

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 ::地圖返回的迭代器:: find()方法,然後使用std :: for_each的(MyMap中。 begin(),incremented_iter,process)。

雙向迭代器都無法扭轉的迭代器,所以無法使用mymap.rend()爲「關開始」來比較在一段時間()循環。

在C++ 11中(或在+14或+17中有沒有乾淨的方法來做到這一點,所以我會有一些期待的)?

+0

'reverse_iterator' –

回答

2

您想要處理每個項目的密鑰X 或更低的,並執行從具有關鍵字X的元素開始的處理,然後向後。你可以做的是在第一個元素上使用reverse_iterator,通過鍵X並創建一個反向迭代器,它指向之前的元素就是你給它的那個。然後,你可以重複,直到「反轉端」:

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 
+0

,我已經錯過了轉換雙向迭代的關鍵實際上是從的std ::地圖返回:: find()方法來一個反向迭代。我不能像你的代碼那樣簡潔。如果X實際上不在地圖中,我的上下文需要我拋出。但這只是一個額外的檢查,所以它仍然非常乾淨。 我不認爲你已經通過gist或GitHub或博客發佈提供幫助功能... – jdzions

+0

@jdzions可能[像這樣](https://gist.github.com/anonymous/dd626b0dccfd70eb134bde5738bf79fa)?請注意,這隻有非常基本的要求,它有一個開始和結束方法。在C++ 17中,我認爲你也有一個尺寸方法。 –