[英]Why doesn't erase support reverse iterators?
我剛剛編寫了以下代碼,很驚訝它沒有編譯:
std::deque<int> container;
// filling the container...
for (auto it = container.rbegin(); it != container.rend(); ++it)
if (*it == 5)
{
container.erase(it);
break;
}
如您所見,我想刪除符合特定條件的最后一個元素(如果有)。
錯誤是
沒有匹配的函數調用 std::deque::erase(std::reverse_iterator...
起初我不相信它是由反向迭代器引起的,但事實確實如此,因為用begin
/ end
替換rbegin
/ rend
解決了它。
所以,2個問題:
我認為需要在整個標准庫中添加的額外重載數量使這成為一項不體面的任務,當沒有“需要”時。
當然,“最優雅”的解決方法幾乎沒有表現力:
container.erase((it+1).base());
......但有一個,而反向迭代器可能不經常使用,足以保證所有將由具有做什么,但包裝上面的代碼行隨處可見過載而造成的額外噪音。
如果您發現自己經常使用它,則可以自己包裝更通用的解決方案:
template <typename ReverseIterator>
auto AsForwardIterator(ReverseIterator rit)
{
std::advance(rit, 1);
return rit.base();
}
那么它只是:
container.erase(AsForwardIterator(it));
而且,坦率地說,這種簡單性似乎不值得在每個容器中都包含所有這些重載。
我不能回答“為什么”的問題,但要回答“如何”——你應該在你的迭代器上調用base()
。 它將返回一個適當的前向迭代器。
這樣做時,請記住反向迭代器和正向迭代器之間的關系。 一開始可能會令人困惑,但實際上很簡單。 如果您有一個包含以下項目的std::vector
:
1, 2, 3, 4, 5
並且您有一個reverse_iterator
rit,在取消引用時為您提供 3,然后*(rit.base)
將等於 4。要了解原因,請記住在普通迭代器中begin()
是可取消引用的,但end()
不是。 在反向迭代器中,屬性必須相同 - rbegin()
必須是可取消引用的,但rend()
不應該 - 即,應該指向容器的開頭之外。
由於根據定義, rend.base()
與begin()
相同(因為 rend 可以構造為reverse_iterator(begin())
,以上所有內容都可以成立的唯一方法是,如果rend.base()
將返回一個開始之后的下一個右側元素 - begin()
. 很容易看出相同的對稱性適用於rend()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.