user4940368
user4940368

Reputation:

Get pointer from vector's element

I want to get a pointer from vector's element which has Fd property set on desired value. Right now I am using this ugly code:

User* Game::GetUser(int fd)
{
    for(auto& v : users)
        if (v.Fd == fd)
            return &v;

    return nullptr;
}

How can I change this code to be more similar to this:

void Game::RemoveUser(int fd)
{
    users.erase(remove_if(begin(users), end(users), [fd](User const& u)
    {
        return u.Fd == fd;
    }), end(users));
}

Or maybe there are other, much better ways to code this?

Upvotes: 1

Views: 96

Answers (1)

Slava
Slava

Reputation: 44238

How can I change this code to be more similar to this

Just use std::find_if with the same predicate:

User* Game::GetUser(int fd)
{
    auto it = find_if(begin(users), end(users), [fd](User const& u)
    {
        return u.Fd == fd;
    }));
    return it == end(users) ? nullptr : &*it;
}

to avoid code duplication you can use result of find_if for erase as well:

  users_type::iterator findUser( int fd)
  {
        return find_if(begin(users), end(users), [fd](User const& u)
        {
             return u.Fd == fd;
        }));
  }

User* Game::GetUser(int fd)
{
     auto it = findUser( fd );
     return it == end( users ) ? nullptr : &*it;
 }

void Game::RemoveUser(int fd)
{
     auto it = findUser( fd );
     if( it != end(users) )
         users.erase( it );
}

you may consider to use different container if such operations has to happen quite often, as both std::find_if and std::remove_if are linear to number of elements. Or you may want to keep users sorted and use std::equal_range() instead of std::find_if() which is log(N), but you would need to use findUser to find proper location to insert or use std::sort after insertion(s).

Upvotes: 3

Related Questions