Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"onEachSubelement(...)" method for C++

I often pack some data into class to prevent mistakes with public/global access and to provide some common methods on it, e.g.:

class GameArea{
    std::vector<Enemy*> enemies;
    std::wstring name;
public:
    void makeAllEnemiesScared();
    Enemy * getEnemy(unsigned index);
};

GameArea is just an simplified example here. It'd a kind of custom container/menager with some specialized methods (but it's not only an container).

The ideal situation is when I know what operations will be executed on each Enemy at once and they occur in several places so I can declare them in GameArea directly (like makeAllEnemiesScared()).

For other cases I can go with:

for(unsigned i=0; i<gameArea->getEnemiesCount(); i++){
    Enemy * enemy = gameArea->getEnemy(i);
    ...
}

But it suffers from some disadvantages:

  • I cannot use C++11 clean&nice for(auto &Enemy : enemies) loop,
  • It's not efficient (so many calls to getEnemy(index)),
  • It's not a purpose for getEnemy(index) to iterate throw all elements - it's usefull in case when we want to select single or few of them, it also has check for index < enemies.size() inside - it's terrible to check it on each element in loop.

NOTE: I think about cases when I do something very special (not worth creating separated method in GameArea, but on each element of GameArea::enemies).

I thought about some GameArea::onEachEnemy(... function ...) method that takes a function (or maybe better an lambda?) as a parameter. Is that good solution?

Or maybe different approach should be used here? Like returning the std::vector from GameArea - which looks a bit "ugly" to me. I don't want user to think he can actually add or remove items to/from that vector directly.

like image 745
PolGraphic Avatar asked Dec 15 '14 12:12

PolGraphic


1 Answers

If you expose the vector itself, or at least iterators begin and end, you can use std::for_each

Then you would use this as

std::for_each(std::begin(enemies), std::end(enemies), foo);  

where foo is the function you want to call on each Enemy.

Again note you don't have to expose the vector itself, you could make methods in GameArea to get iterators so the call could be like

std::for_each(gameArea->GetEnemyBegin(), gameArea->GetEnemyEnd(), foo);  
like image 70
Cory Kramer Avatar answered Oct 04 '22 23:10

Cory Kramer