2013-04-17 50 views
2

我曾經瞭解到從容器中擦除元素的一般方法是通過erase-remove-idiom。但是我驚訝地發現,至少g ++的STL實現不會爲std :: list重載std :: remove(),因爲在這種情況下,通過指針操作重新排序可以節省大量對象分配。如何爲std :: list重載std :: remove?

是否有一個原因,C++標準沒有要求這樣的優化?但我的主要問題是如何重載std :: remove()(它不必是g ++以外的可移植的),所以我可以提供一個使用list :: splice()/ list :: merge()的實現。我嘗試了幾個簽名,但充其量得到一個含糊不清的錯誤,例如:

template <typename T> 
typename std::list<T>::iterator 
remove(typename std::list<T>::iterator first, 
     typename std::list<T>::iterator last, const T &v); 

P.S:我很抱歉,我不太清楚。請忽略這些函數來自std命名空間以及它們具體做什麼。我只是想了解更多關於C++中的模板/類型轉換/重載規則。

+5

你應該使用['的std ::目錄:: remove'(http://en.cppreference.com/w/cpp/container /列出/刪除)。 –

+0

這可能是[XY問題](http://meta.stackexchange.com/questions/66377)。 –

回答

1

list::removelist::erase單獨會做你見過的擦除/刪除成語爲媒介做的事情。

remove值或謂詞。單個迭代器或範圍的erase

+0

謝謝,但我知道列表成員函數,但它不回答我的問題。假設在我的代碼中有相當多的模板函數使用erase-remove來處理泛型容器,而且我不想爲std :: list重載所有的模板函數。 –

+0

嗨,@ antje-m。您可能誤導了擦除/刪除習慣用法是所有容器的一般方法。它對* most *容器類型無效。另外,如果它*用在'std :: list'上,它會比我鏈接的函數慢得多。 –

+0

@ antje-m也許你會從詢問有關「容器的通用卸妝器」而不是詢問*如何*以擦除/去除正確方法中獲益更多。祝你好運! –

0

您收到的建議是好的,但不是通用的。例如,對於std::vector是有利的,但是對於std::list完全是必要的,因爲std::list::erase()std::list::remove()已經做正確的事情。他們會完成您請求的所有指針魔術,std::vector::erase()無法完成,因爲其內部存儲空間不同。這就是爲什麼std::remove()不是專門用於std::list的原因:因爲在這種情況下不需要使用它。

2

它不是強制性的,因爲它不只是一個優化,它已經從你所期望的順序容器不同的語義:

std::list<int> l; 
l.push_back(1); 
l.push_back(2); 

std::list<int>::iterator one = l.begin(); 
std::list<int>::iterator two = l.end(); --two; 

if (something) { 
    l.erase(remove(l.begin(), l.end(), 1), l.end()); 
    // one is still valid and *one == 2, two has been invalidated 
} else { 
    l.remove(1); 
    // two is still valid and *two == 2, one has been invalidated 
} 

至於實際的問題:ISWYM,我堅持的時刻如何編寫一對函數模板,以便一個匹配任意迭代器,另一個匹配列表迭代器,而不會產生歧義。

請注意,list<T>::iterator是與some_other_container<T>::iterator不同類型的標準,實際上並沒有任何保證。因此,雖然在實踐中你會希望每個容器都有自己的迭代器,但原則上這種方法有點不對,因爲你建議把過載放在std之內。您不能單獨使用迭代器對其相應的容器進行「結構」更改。

你可以做到這一點毫不含糊:

template <typename Container> 
void erase_all(Container &, const typename Container::value_type &); 

template <typename T> 
void erase_all(std::list<T> &, const T &); 
相關問題