1

I have a vector of objects :

std::vector<QueuedMessage> _messages;

And trying to remove all objects with erase-remove idiom:

void MessageQueue::removeFromQueue(){
    _messages.erase(std::remove_if(_messages.begin(),_messages.end(),wasMessageSend),_messages.end());
}

My compare function:

bool MessageQueue::wasMessageSend(const QueuedMessage& mess){

            return mess.canSendMessage();
        }

And compare function inside the objects class:

bool QueuedMessage::canSendMessage() const{
    return (SDL_GetTicks() >= startTick);
}

However, I receive this error:

error: must use '.*' or '->*' to call pointer-to-member function in '((__gnu_cxx::__ops::_Iter_pred<bool (MessageQueue::*)(const QueuedMessage&)>*)this)->__gnu_cxx::__ops::_Iter_pred<bool (MessageQueue::*)(const QueuedMessage&)>::_M_pred (...)', e.g. '(... ->* ((__gnu_cxx::__ops::_Iter_pred<bool (MessageQueue::*)(const QueuedMessage&)>*)this)->__gnu_cxx::__ops::_Iter_pred<bool (MessageQueue::*)(const QueuedMessage&)>::_M_pred) (...)'|

Is it a problem that I´m not using a vector of pointers? Or am I missing something? Thanks.

3
  • 1
    wasMessageSend is not a function. It's a member function. Commented Apr 23, 2017 at 15:12
  • 1
    wasMessageSend in the remove_if() call is a pointer to a member function. Commented Apr 23, 2017 at 15:13
  • As alternative, you can make wasMessageSend static. Commented Apr 23, 2017 at 18:48

2 Answers 2

3

The predicate passed to std::remove_if is supposed to be a unary predicate with signature like bool pred(const Type &a);. That means it will be invoked with the element as the argument. But wasMessageSend is a member function so, besides the argument, it also needs an instance to be invoked on. So it can't be used with remove_if directly.

You can use lambda (since C++11) with it like:

_messages.erase(std::remove_if(
    _messages.begin(),
    _messages.end(),
    [this](const QueuedMessage& q) {
        return wasMessageSend(q);
    }
));
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks! It works! I think I totally forgot that this problem can be caused by using a member function as a comparator because I thought that it has a problem with a member function of the stored object not the class storing the vector.
@BoundaryImposition Thanks for the editing! But why 3 spaces for indent?
@songyuanyao: Why not?
@BoundaryImposition Because I'm just used to 2 or 4. Yes I know it's a personal opinion issue..
This is why tab-indentation is far superior, so that you can render the code anyway you choose without imposing your choice on other people (much like you can choose the font, and colour). Furthermore, the indentation of your code gains strict and unambiguous semantics (one tabspace = one level of indentation) that could be autonomously interpreted then handled in any way you like. Sadly, that works poorly on the web, so you are stuck with my three spaces. :)
|
1

Since wasMessageSend is a member function of your class MessageQueue, you need to "bind it" to an object (in this case, this) using std::bind

void MessageQueue::removeFromQueue(){
_messages.erase(std::remove_if(_messages.begin(),_messages.end(),
    std::bind(&MessageQueue::wasMessageSend, this, std::placeholders::_1), // bind this
    std::_messages.end());
}

Of course, this is not the only way, you may for example define a lambda predicate on the spot... but this method shows how to use a member function as a predicate.

5 Comments

You may refer to song's answer
@BoundaryImposition I know that answer works too, but I'm eager to know why you consider it better or say "less antiquated" :). To my eyes this syntax is a bit simpler.
Looks a lot less simple to me. A lambda expression is very expressive, which is why it was added to the language
@A.S.H You might want to read this post, or the book Effective Modern C++ Item 34: Prefer lambdas to std::bind for further infos.
I respect your opinions but I will always prefer to bind when the predicate is ready, there, but has the only "handicap" of being a member function. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.