1

ALL,

Consider following code:

class CPlayer
{
public:
    CPlayer(bool new) { m_new = new; };
    bool IsNewPlayer() { return m_new; }
private:
    bool m_new;
};

int main()
{
    std::vector<CPlayer> players_pool;
    players_pool.push_back( false );
    players_pool.push_back( false );
    players_pool.push_back( true );
    players_pool.push_back( false );
}

Now what I'm looking for is to remove the players which has m_new as true.

Is it possible to do something like this:

players_pool.erase( std::remove( players_pool.begin(), players_pool.end(), players_pool.at().IsNewPlayer() ), players_pool.end() );

Now everywhere the examples given are for simple integers and not for the class objects.

Is there an easy way to perform such an operation?

And I need it to work in MSVC 2010 and XCode 4 with 10.6 SDK.

Note: The code given is a simplified version of the actual code I'm working on. Class CPlayer has a lot more fields than I put here but they are not relevant to this post.

Thank you.

P.S.: I found this but my question here is if it will work on OSX. My remover looks like this:

struct Remover : public std::binary_function<CPlayer,void,bool>
{
public:
    bool operator()(const CPlayer &player) const
    {
        return player.IsNewPlayer();
    }
};
Community
  • 1
  • 1
Igor
  • 5,620
  • 11
  • 51
  • 103
  • Be carefull: `new` is a keyword in C++. You cannot use it as a identifier. – Manu343726 Jul 13 '13 at 08:42
  • @Manu343726, yes, I'm. That's why I wrote "Note" in the post. ;-) – Igor Jul 13 '13 at 08:48
  • As to the question: I'm not entirely sure I understood what you mean, but `vector` is a generic template, the remove-erase idiom works for any data type it is initialized with. The destructors will be called properly. –  Jul 13 '13 at 08:49
  • @Manu343726 by the way, this is not related neither to Xcode nor to Visual Studio. It's a question about the C++ language and standard library. (Which, again, is ***not*** the STL. The STL is something entirely different.) –  Jul 13 '13 at 08:49

2 Answers2

1

Yes, it is possible. The standard library provides std::remove, which removes objects which are equal to some specified value (using the == operator), and it has std::remove_if, which, instead of a value, takes a function which is called on the object, and if it returns true, it indicates that the object should be removed. So simply write a function which defines the condition you want, and use that:

players_pool.erase( std::remove_if(
  players_pool.begin(),
  players_pool.end(),
 [](const CPlayer& p){ return p.IsNewPlayer(); }),
 players_pool.end() );

Note, I used a lambda for the function passed to remove_if. If your compiler doesn't support that yet, you can simply define the function separately, either as a function (with the signature bool func(const CPlayer&);, or a function object with an bool operator()(const CPlayer&)

jalf
  • 243,077
  • 51
  • 345
  • 550
  • @yalf, will it be supported by the XCode and 10.6 SDK? – Igor Jul 13 '13 at 09:03
  • @Igor I don't know, but check my update :) You don't need to use the lambda expression, I just used that to simplify my example – jalf Jul 13 '13 at 09:04
0

Simply use std::remove_if and a lambda function as predicate:

players.erase( std::remove_if( players.begin() , 
                               players.end() , 
                               [](const Player& player) { return player.IsNewPlayer(); } 
                              ) );

Lambdas are supported by VC10 (VS2010 C++ compiler).

In XCode you are using Clang? It supports lambda expressions too.

On the other hand, if your compiler not supports C++11 lambdas, your functor is the correct way.

Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • which XCode/SDK starts supporting lambda expression? I'm not sure 10.6 supports them, but I can't be sure it is supported such functor (meaning std::bind2nd). – Igor Jul 13 '13 at 09:02
  • Xcode4.4 uses LLVM4.0, wich includes lambdas: http://developer.apple.com/library/ios/#documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_4_4.html – Manu343726 Jul 13 '13 at 09:06
  • how do I call my functor? "std::bind2nd( Remover() )" gives compiler error "Expect 2 arguments - one provided". Thank you. – Igor Jul 13 '13 at 18:25
  • You want to use a unary function, because you want only a function that gets a Player and return a boolean (Check `std::find_if` documentation. The signature of the predicate is very clear). You are using a binary functor. Your `operator()`its fine, but the type of the functor not. Use `std::unary_function` instead: http://en.cppreference.com/w/cpp/utility/functional/unary_function – Manu343726 Jul 13 '13 at 19:45
  • @Igor or don't use anything. `std::unary_function` is not required, and in fact is deprecated in C++11. – juanchopanza Jul 14 '13 at 07:16