1

Fairly simple question.

I have a Bullet object where at one point when the bullet collides with an object, it gets destroyed and removed from a vector of Bullets.

Each Bullet object has a reference to the vector/list of bullets.

How do I remove it using the this keyword inside the Bullet class when this happens?

void collide(){
    //error C2678: binary '==': no operator found which takes a left-hand operand of type 'Bullet'
    //(or there is no acceptable conversion)
    bullets->erase(std::remove(bullets->begin(), bullets->end(), *this), bullets->end());
}

So yeah that code gives me a strange error. I need to know how to do it without iterating over the vector of bullets using a while/for loop and just using vector functions. Obviously the current method isn't working as it's spewing out the error as commented in the code.

I also tried using find() instead of remove(), same error.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Joe Bid
  • 465
  • 8
  • 24
  • 6
    Do you have an equality operator (i.e. `operator==`) for the `Bullet` class? – Some programmer dude Jan 26 '15 at 08:42
  • 6
    The error message could hardly be clearer. And `std::remove` *does* iterate over the vector, so beware that this approach has linear cost regardless. – Kerrek SB Jan 26 '15 at 08:42
  • I do not have one, but I could really use a solution. I've seen other examples on here that did not need to implement the operator== yet they still worked with this method. Honestly though, just how do I remove an element (this) from a vector? – Joe Bid Jan 26 '15 at 08:54
  • 3
    You should implement operator== or try using std::remove_if with lambda to compare. For ex.: http://stackoverflow.com/questions/24086717/why-does-remove-if-lambda-expression-require-the-assignment-operator – SGrebenkin Jan 26 '15 at 08:56
  • 1
    @JoeBid Those examples used a vector of something that had an equality operator (integers, pointers, `std::string`s...). There is no way around that requirement. – molbdnilo Jan 26 '15 at 08:58
  • Something about your `Bullet` prevents the compiler from being able to generate `operator==` automatically. It should be obvious that functions like `find` and `remove` need to be able to test if a `Bullet` is equal to the one you're finding or removing. So you must implement it. – Drew Dormann Jan 26 '15 at 09:00
  • Rather than run through the array each time a bullet is removed it may be faster to mark bullets as deleted through some flag and, if you have another function that processes the list of bullets, add code there to erase those marked for deletion. That way you can iterate over the vector once to erase many bullets. – Galik Jan 26 '15 at 09:17

3 Answers3

2

you need to implement the == operator in the bullet class. if you want to delete an item according to it's memory address , you can simple iterate over the vector and find the element naively :

    for (Bullet& bullet : bullets){
        if (&bullet == this){
          bullets.erase(bullet);
            break;
         }
     }
David Haim
  • 25,446
  • 3
  • 44
  • 78
  • 3
    It's not safe. Vector reallocates its content while erasing, so iterator is invalidated. Explained here http://stackoverflow.com/questions/10360461/removing-item-from-vector-while-in-c11-range-for-loop – SGrebenkin Jan 26 '15 at 09:06
2

Try this:

std::remove_if( bullets.begin(), bullets.end(), 
   [this] (const Bullet& s) {
      if (&s == this)
          return true;
      return false;
   }
);
Serebrov
  • 83
  • 4
1

You need to get an iterator to the object you want to erase. You can get it by using the difference between the first and the current object:

bullets->erase(bullets->begin() + (this - &bullets.front()));

Note that this will destroy the object whose method you are currently executing, i.e., you can't access any of the member's objects afterwards.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380