I'm practicing C++, so this is not code that will go into production, but I'm very curious to know:
I have a vector of pointers to objects of type Player
:
std::vector<Player*> _players;
Each player returns me his name as std::string
when I call it's method get_name()
, for example:
std::string player0_name = _players[0]->get_name();
I want to pass all player names to a function that expects them as reference to a vector of strings:
void all_player_names( std::vector< std::string >& );
Now I know it would be easy to do this via some temporary variable. I could first create a vector of strings, store all player names there, then pass it to the function all_player_names
as reference.
But I'm looking for a way of doing that without having to create a temporary variable. It should be something similar like a list comprehension in Python. It has to iterate over the array of Player
pointers, call the get_name()
function on each of them, build a vector out of the returned strings and directly pass it to the function all_player_names
. I'm assuming it should be possible with lambda functions and some algorithm from the STL, but I don't know which one.
So it should look more or less like that:
all_player_names(<function that i'm looking for>(
_players, [](Player* p) { return p->get_name();}
);
Is there such an algorithm in the STL?
Easiest way would be using accumulate and using a temporary variable that will be passed through the binary op and returned:
std::accumulate(_players.begin(), _players.end(),
std::vector<std::string>(),
[](std::vector<std::string>& vector, const Player* elem)
{
vector.push_back(elem->get_name());
return vector;
});
Thanks to move semantics it should have almost no performance overhead in C++11.
In my opinion it is better to use standard algorithm std::transform instead of std::accumulate. The semantic of std::transform is more clear in this case compared with the semantic of std::accumulate. For example
struct Player
{
public:
Player( const std::string &s ) : s( s ) {}
const std::string & get_name() const
{
return s;
}
private:
std::string s;
};
std::vector<Player *> v1;
v1.push_back( new Player( "Hello" ) );
v1.push_back( new Player( "Player" ) );
std::vector<std::string> v2;
v2.reserve( v1.size() );
std::transform( v1.begin(), v1.end(), std::back_inserter( v2 ),
std::mem_fun( &Player::get_name ) );
for ( const std::string &s : v2 ) std::cout << s << ' ';
std::cout << std::endl;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With