• Create Account

### #ActualAllEightUp

Posted 15 September 2013 - 01:25 PM

Having had this sort of problem in the past (more common with my SOA organized data when I had to do AOS access style in specific cases), I generally used a helper+filtered iterator approach to simplify things, though it does not completely remove the 99 cases, it should at least reduce the code overlaps:

Original
for (a=0; a<maxcavemen; a++)
{
if ! cm[a].active continue;
// do some stuff with active PC cm[a]
}
Abstract iteration version:
typedef std::function< void ( Caveman& ) > CavemanUpdate_t;
IteratateCavemen( Cavemen& cm, CavemanUpdate_t update ) {
for( Caveman& c : cm ) update( c );
}
This is not really going to do any good but it is the start to writing:

typedef std::function< bool ( Caveman& ) > Filter_t;
typedef std::function< void ( Caveman& ) > CavemanUpdate_t;
IteratateCavemen( Cavemen& cm, Filter_t filter, CavemanUpdate_t update ) {
for( Caveman& c : cm ) if( filter( c ) ) update( c );
}

So, the benefit of this is to get rid of that "if( active ) etc" stuff and move it to a helper class. So you can write something as follows:

struct UpdateFilters
{
static bool IsLiving( Caveman& cm ) {return cm.alive && cm.active;}
};

IterateCavemen( cavemenList, std::bind( &UpdateFilters::IsLiving, std::placeholders::_1 ), []( Caveman& c )
{
// Do your update code here.
} );
};

This does not attempt to correct code structure though I tend to agree with others that you might consider this is a problem, but that's completely up to you. What it does do though is allow you to break up the functionality such that in the future at least the key pieces of the code beyond the localized "update call" are nicely organized somewhere central.

NOTE: Obviously I'm using C++11 in the above. You can of course replace it all with TR1, Boost or just plane old functors. Of course each of the other solutions has it's own downfalls, generally in terms of typing.

### #1AllEightUp

Posted 15 September 2013 - 12:56 PM

Having had this sort of problem in the past (more common with my SOA organized data when I had to do AOS access style in specific cases), I generally used a helper+filtered iterator approach to simplify things, though it does not completely remove the 99 cases, it should at least reduce the code overlaps:

Original
for (a=0; a<maxcavemen; a++)
{
if ! cm[a].active continue;
// do some stuff with active PC cm[a]
}
Abstract iteration version:
typedef std::function< void ( Caveman& ) > CavemanUpdate_t;
IteratateCavemen( Cavemen& cm, CavemanUpdate_t update ) {
for( Caveman& c : cm ) update( c );
}
This is not really going to do any good but it is the start to writing:

typedef std::function< bool ( Caveman& ) > Filter_t;
typedef std::function< void ( Caveman& ) > CavemanUpdate_t;
IteratateCavemen( Cavemen& cm, Filter_t filter, CavemanUpdate_t update ) {
for( Caveman& c : cm ) if( filter( c ) ) update( c );
}
So, the benefit of this is to get rid of that "if( active ) etc" stuff and move it to a helper class. So you can write something as follows:

[code=auto:0]
struct UpdateFilters
{
static bool IsLiving( Caveman& cm ) {return cm.alive && cm.active;}
};

IterateCavemen( cavemenList, std::bind( &UpdateFilters::IsLiving, std::placeholders::_1 ), []( Caveman& c )
{
// Do your update code here.
} );
};

This does not attempt to correct code structure though I tend to agree with others that you might consider this is a problem, but that's completely up to you. What it does do though is allow you to break up the functionality such that in the future at least the key pieces of the code beyond the localized "update call" are nicely organized somewhere central.

NOTE: Obviously I'm using C++11 in the above. You can of course replace it all with TR1, Boost or just plane old functors. Of course each of the other solutions has it's own downfalls, generally in terms of typing.

PARTNERS