2012-11-11 83 views
1

我有一個boost :: ptr_vector包含指向類「holdable」的指針。如何擦除「this」from boost :: ptr_vector

boost::ptr_vector<holdable> items; 

我從可保持類中添加新的項目到這種載體是這樣的:

currentplanet->items.push_back(this); 

其中currentplanet是指向包含ptr_vector的類的對象。這很好。

我很困惑的是如何從它自己的類中的函數中從ptr_vector中刪除條目。我想:

currentplanet->items.erase(std::find(currentplanet->items.begin(), 
            currentplanet->items.end(), 
            this)); 

如按照回答類似的問題在這裏:How to erase elements from boost::ptr_vector,但我已經很明顯了問題的地方,可能對於使用的「本」。

在嘗試編譯,我收到來自stl_algo.h說

stl_algo.h|174|error: no match for 'operator==' in '__first.boost::void_ptr_iterator<VoidIter, T>::operator* 
    [with VoidIter = __gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, 
    T = holdable]() == __val'| 

我敢肯定,這東西很明顯,但我可能得到的ptr_vector的間接混淆...感謝任何答案錯誤提前!

+1

你的設計在任何情況下都是有缺陷的,我想。一個'ptr_vector' *擁有*中的指針。如果你已經有了'this',那麼* else *擁有這個對象。將它添加到'ptr_vector'是沒有意義的。只需使用'std :: vector '作爲所有事物的非擁有參考。 – Xeo

回答

2

至於其他寫道 - 這是事實,ptr_vector需要你的對象的所有權,但如果你堅持要能夠對從ptr_vector本身被刪除對象 - 使用find_if,找不到:

Holdable* ptr = this; 
currentplanet->items.erase(std::find_if(currentplanet->items.begin(), 
             currentplanet->items.end(), 
             [ptr](const Holdable& other) 
             {return ptr == &other;})); 

注這find*this使用可能會發現其它物體等於*this ...


對於編譯器仍然不支持lambda表達式(這件事從開始[ptr]),使用你自己的謂詞:

struct CompareToPtr { 
    CompareToPtr(Holdable* ptr) : ptr(ptr) {} 
    bool operator() (const Holdable& other) const { return &other == ptr; } 
    Holdable* ptr; 
}; 
currentplanet->items.erase(std::find_if(currentplanet->items.begin(), 
             currentplanet->items.end(), 
             CompareToPtr(this))); 
+0

謝謝,但我恐怕會拋出一個 holdable.h | 48 |錯誤:期望的主表達式'['token | (其中第48行以上述代碼段中的[ptr]開頭)。我錯過了明顯的東西? – Riot

+0

@Riot:PiotrNycz的代碼片段使用C++ 11 lambda表達式,您的編譯器可能不支持(或可能需要指定啓用此類支持的選項)。如果C++ 11不適合你,你可以使用'find_if()'謂詞參數(lambda被使用的)一個函子,甚至是一個普通的舊函數。 –

+1

@Riot - 我爲C++ 03添加了... – PiotrNycz

2

我明白的std ::發現需要第三PARAM值(不是指針),所以你傳遞一個[「開始」,「結束」)範圍,即尋求和價值,你尋求

這是你的意思嗎?

currentplanet->items.erase(std::find(currentplanet->items.begin(), 
            currentplanet->items.end(), 
            *this)); 

注意*此

+1

ptr_vector中的其他對象可能等於'* this' - 所以不一定會返回this對象迭代器。 – PiotrNycz

+0

恐怕這是我第一次嘗試 - 這似乎並不是有效的代碼。編譯器說: stl_algo.h | 174 |錯誤:'__first.boost :: void_ptr_iterator :: operator *'與'operator =='不匹配[with VoidIter = __gnu_cxx :: __ normal_iterator >>,T = holdable]()== __val'| – Riot

2

Alf is correct,但我認爲shoould被發現的原因,是有些奇特,以boost::ptr_vector(以及其他相關boost::reversible_ptr_container容器)。通常,對容器元素的迭代器將取消引用容器的引用value_type

boost:ptr_vector<T>::value_typeT*的typedef;然而,取消引用boost::ptr_vector<T>::iterator不會導致T*引用。

從升壓文檔(http://www.boost.org/doc/libs/1_52_0/libs/ptr_container/doc/reversible_ptr_container.html):

Also notice that

typedef ... iterator 

allows one to iterate over T& objects, not T*.

解引用一個boost::ptr_vector<T>::iterator導致T&。這就是爲什麼你被ptr_vector的間接性弄糊塗了,這就是爲什麼std::find()的最後一個參數需要是holdable對象而不是holdable*

最後,請注意Xeo關於ptr_vector對於指針所有權的評論應該被理解 - 在非常有限的情況下,對象想要刪除它本身可能是有意義的,但是您應該完全理解,那erase()調用,你不能再做任何事情與對象。如果這不是你需要的行爲,你可能需要考慮使用release(),而不是erase(),它將釋放容器對指針的所有權並將其從容器中移除(這樣對象不會被銷燬)。

+0

謝謝,但正如我評論Alf的回覆,使用「* this」會產生編譯器錯誤。有什麼方法可以讓我知道嗎? 順便說一句,爲了澄清 - 這實際上是在對象要刪除自己的情況下。 – Riot

+1

我認爲在這一點上,問題是你沒有'運算符==()',它允許比較可holdable對象。你可能想發佈一個小而完整的例子,說明編譯器顯示你看到的錯誤(這個例子可能需要一個'class holdable',但你可能不需要'currentplanet'對象就可以離開。 –

+1

但是,您應該注意到PiotrNycz的答案 - 您肯定需要處理可比較相同的「可holdable」對象的問題 - 或者通過使用對象地址的find_if()的解決方案或者不允許這樣的條件在'items'中的對象之間發生(這可能是處理問題的一種相當脆弱的方式)。 –