Skip to main content
gamedev.net
🔒 Locked

Vector access: iterators?

Started by DaBono 7 replies 1.2k views
Original Post
DaBono
DaBono
Say I have a std::vector of Entity's. I want to invoke the doUpdate-method on all of them. I would then write:

for( size_t i = 0; i < m_entities.size(); i++ )
   m_entities.doUpdate();
However, I often see iterators used, which would give:

for( std::vector<Entity>::iterator i = m_entities.begin(); 
                                   i != m_entities.end(); ++i )
   (*i).doUpdate();
The question: I find the first solution more readable and easier to type. However, what are the reasons to use the second method? Coherency with lists (where you can't use []), speed, l33tness??
persil
persil
It's up to you, but if you want to create a templated function that accepts any kind of list, you'll have to use the iterator method, because only the vector accepts the [] operator, as you already pointed out.

You use the [] operator in cases where you used a vector because you needed random access.
blizzard999
blizzard999
Quote:
Original post by DaBono
The question: I find the first solution more readable and easier to type. However, what are the reasons to use the second method? Coherency with lists (where you can't use []), speed, l33tness??


The second solution is a good habit because you can iterate an abstract structure; so if you change the data structure (for example a list or a map) you have not to change your existing code.
In this case is also a good practice the use of typedef.

typedef std::vector<Entity> ENTITIES;// or typedef std::list<Entity> ENTITIES;...//later, or in other modules, you will use the same code...for( ENTITIES::iterator i = ...)
dave
dave
Also, supposing it is a string iterator then the string.insert() is best used by passing an interator for the insertion point.

ace
Trap
Trap
std::for_each(m_entities.begin(),m_entities.end(),uglyadapter(&Entity::doUpdate))

is what you are looking for (with a suitable uglyadapter thingy).

Especially for the l33tness part ;)
Couvillion
Couvillion
Quote:
Original post by Trap
std::for_each(m_entities.begin(),m_entities.end(),uglyadapter(&Entity::doUpdate))

is what you are looking for (with a suitable uglyadapter thingy).

Especially for the l33tness part ;)


The boost::lambda libraries can provide a suitable uglyadapter thingy:

#include<boost/lambda/lambda.hpp>#include <boost/lambda/bind.hpp>using namespace std;using namespace boost::lambda;...for_each((m_entities.begin(),m_entities.end(), bind(&Entity::doUpdate, _1));
~~C--O -
jdhardy
jdhardy
Why use Boost.Lambda for that?

#include <algorithm>#include <functional>using namespace std;for_each(m_entities.begin(), m_entities.end(), mem_fun_ref(&Entity::doUpdate));

Should work, but I don't have a compiler handy to check.
Couvillion
Couvillion
Quote:
Original post by jdhardy
Why use Boost.Lambda for that?

#include <algorithm>#include <functional>using namespace std;for_each(m_entities.begin(), m_entities.end(), mem_fun_ref(&Entity::doUpdate));

Should work, but I don't have a compiler handy to check.


I tested it, and it does work. The only advantage I can see to the boost::lambda is the same code would work with a vector of Entity*, but that's not what he has, so may as well stick with the standard library.
~~C--O -
MaulingMonkey
MaulingMonkey
Quote:
Original post by Couvillion
I tested it, and it does work. The only advantage I can see to the boost::lambda is the same code would work with a vector of Entity*, but that's not what he has, so may as well stick with the standard library.


That's a simple matter of replacing mem_fun_ref with mem_fun during that situation, or boost::mem_fn (not a typeo) if you truely want them both. Bind is a bit much for something so simple :-).

Quote:
I find the first solution more readable and easier to type.


That's because it is. The advantages of the second would be interoperability with any container type (the core concept of iterators). It's what lets std::for_each work with so many containers. The key here is it allows for more reuse. Although an ugly heart may have std::for_each, it glistens on the outside, beautiful, like raindrop. Code reuse taken to the extreme. They're reusing the humble for loop for hecks sake!

My continued use of std::for_each indicates I do not consider this a bad thing.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.