0

Edit: @Holt helped me, the solution is to pass an instance of Engine if hasCollided is non-static:

std::bind(&Engine::hasCollided, this, ball, _1);

I have a function which returns true or false whether a brick is hit by a ball.

I want to erase a brick which was hit from the vector. I managed to get the idiom working with simple vector of numbers and a bool function, but I get strange errors when I try the same with vector of objects.

Private members:

Ball ball;
std::vector<Brick> bricks;

Collision check:

bool Engine::hasCollided(Ball& object1, Brick& object2)
{
    //do some checks
    return 1;
}

My attempt:

using namespace std::placeholders;

auto f = std::bind(hasCollided, ball, _1);
bricks.erase(std::remove_if(bricks.begin(), bricks.end(), f), bricks.end());

Error happens in the predefined_ops.h right here:

template<typename _Iterator>
    bool
    operator()(_Iterator __it)
    { return bool(_M_pred(*__it)); }
    };

And the compiler spits out 92 errors. Please help me fix that

Example error:

required from '_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator<Game::Brick*, std::vector<Game::Brick> >; _Predicate = __gnu_cxx::__ops::_Iter_pred<std::_Bind<std::_Mem_fn<bool (Game::Engine::*)(Game::Ball&, Game::Brick&)>(Game::Ball, std::_Placeholder<1>)> >]'

  • Which errors does it spit out? (Please don't copy all 92 of them, though!) – hlt Apr 07 '17 at 09:33
  • You probably want to pass argument by const reference. – Jarod42 Apr 07 '17 at 09:35
  • 2
    Is `Engine::hasCollided` `static` ? (if not you have to add it in the binding). – Jarod42 Apr 07 '17 at 09:37
  • Example error: `required from '_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = __gnu_cxx::__normal_iterator >; _Predicate = __gnu_cxx::__ops::_Iter_pred(Game::Ball, std::_Placeholder<1>)> >]'` –  Apr 07 '17 at 09:41
  • It's not static, I'll try –  Apr 07 '17 at 09:42
  • 1
    @daavid245 [Edit] your question, and add such information in there. All information, necessary to answer the question, must be present in the question itself, and not buried in the comments. – Algirdas Preidžius Apr 07 '17 at 09:43
  • @AlgirdasPreidžius done :) –  Apr 07 '17 at 09:45
  • 1
    @daavid245 You need to pass an instance of `Engine` to `std::bind` if `hasCollided` is a not static. If your code is inside a method of `Engine`, you could try `std::bind(&Engine::hasCollided, this, ball, _1)`. – Holt Apr 07 '17 at 09:53
  • @Holt this looks like an answer – n. m. could be an AI Apr 07 '17 at 09:59

1 Answers1

0

Since hasCollided is a not a static function, you need to pass an instance of Engine to std::bind.

Assuming you are doing the erase/remove inside a method of Engine, you can do the following:

auto f = std::bind(&Engine::hasCollided, this, ball, _1);
//                                       ^^^^
Holt
  • 36,600
  • 7
  • 92
  • 139
  • I know it's late but could you tell why do I need to pass the object to std::bind? –  Apr 07 '17 at 21:40
  • @daavid245 `Engine::hasCollided` is method, so it work on an instance of the object (`this`). If you want to call `hasCollided`, you need an instance of `Engine`, otherwise you have no `this` object to work with. If your `hasCollided` function does not use members of the `this` object, then it should probably be made `static`, in which case you do not need to pass `this` to `std::bind`. – Holt Apr 08 '17 at 11:00