c++boostptr-vector

How to erase "this" from boost::ptr_vector


I have a boost::ptr_vector containing pointers to class "holdable".

boost::ptr_vector<holdable> items;

I add new items to this vector from within the holdable class like this:

currentplanet->items.push_back(this);

where currentplanet is a pointer to an object of the class containing the ptr_vector. This is all fine.

What I'm confused about is how to remove an entry from the ptr_vector from a function within its own class. I'm trying:

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

as in accordance with the answer to a similar question here: How to erase elements from boost::ptr_vector, but i've obviously gone wrong somewhere, probably with regard to the use of "this".

On trying to compile, i receive an error from stl_algo.h saying

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'|

I'm sure it's something obvious, but i'm probably getting confused by ptr_vector's indirection... thanks for any answers in advance!


Solution

  • As other wrote - it is true that ptr_vector takes ownership of your object, but if you insist to be able for object to be removed from ptr_vector by itself - use find_if, not find:

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

    Note that find used with *this might find other object which is equal to *this...


    For compilers still not supporting lambda expression (this thing starting from [ptr]), use your own predicate:

    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)));