Archives pour la catégorie «C++11»

Bout de code facilitant l’emploi de std::forward_list

Une fois n’est pas coutume, un article un peu technique qui vise à faciliter – pour peu que l’on ne l’utilise souvent – l’emploi du container std::forward_list du nouveau standard C++11. Ce container comble une lacune de la librairie standard, à savoir la mise à disposition d’une liste simplement chaînée limitant l’overhead et favorisant la rapidité d’exécution. On remarque ainsi que le container ne dispose pas de membres size()1.

Je ne vais présenter plus avant pourquoi utiliser ce type de container mais il peut être utile pour gérer beaucoup de munitions par exemple.

Une autre difficulté à l’utilisation est que pour supprimer un élément via sa position (et non sa valeur => linéaire) , il faut connaîre l’itérateur précédent celui qu’on veut supprimer. Outre ceci, il faut récupérer l’itérateur retourné par la fonction membre erase_after pour garder des itérateurs valides. Bref réécrire le même code à la longue devient rébarbatif d’où ce court exemple qui propose un exemple qui prend en paramètre une instance du container, une classe et une fonction membre qui retourne vrai si elle veut supprimer l’élément traité de la liste:

template<class T,class PARAM>
void loopThroughBatteries( std::forward_list<PARAM>& container, T* instance, bool (T::*fn)(PARAM) )
{

FUS_ASSERT( (instance != nullptr) && (fn != nullptr) && "You should pass a function and an instance");

 auto beginBattery( container.begin() );
 auto beforeCurrentBatteryIt( container.before_begin());
 auto lastBattery( container.end() );

 auto currentBatteryIt = beginBattery;

 while( currentBatteryIt != lastBattery )
 {
 //! quand retourne vraie on supprime
 if( (instance->*fn)( *currentBatteryIt ) ){

 currentBatteryIt = container.erase_after( beforeCurrentBatteryIt );
 }
 else {
 beforeCurrentBatteryIt = currentBatteryIt;
 currentBatteryIt++;
 }
}
}

Exemple d’utilisation:


loopThroughBatteries( _activeBatteries, this, &IFleetForwardListBased:: periodicBatteryCheck );

avec

bool
IFleetForwardListBased::periodicBatteryCheck( IStaticBattery* battery )
{

 bool stillOffscreen = getPlayState()->isEntityOufOfScreen(battery);
 battery->stillOutOfScreen( stillOffscreen );

 if( battery->getOffscreenCounter() > 3 )
 {

 battery->onTimeoutDisparition();
 _INFO << "time out death";
 return true;
 }

 return false;
}

Bon maintenant les bons diront qu’on peut faire exactement la même chose via :


_activeBatteries.remove_if( std::bind1st( std::mem_fun(&IFleetForwardListBased::periodicBatteryCheck),this) );

 

Malgré tout j’espère que cela vous aidera dans votre utilisation de std::forward_list.