Archives pour la catégorie «C++»

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.

 

Passage à PugiXml

Bonjour,

Je viens ici faire un peu de pub pour l’excellente « librairie » C++ PugiXml. J’avais envie de la tester depuis longtemps et cette envie s’est concrétisée alors que je me heurtais aux manques de mon wrapper TinyXml (inhérents à TinyXml). Ne voulant pas réécrire (et surtout maintenir !) toute une librairie,  je l’ai donc testée (avec comme 2nd remplaçant irrXML, la librairie utilisée par irrlicht et qui existe en standalone). PugiXml = TinyXml + « tout » ce qui manque à TinyXml :

  1. La documentation est top !
  2. 1 seul fichier source ! donc encore plus compact que TinyXml
  3. des projets livrés avec l’archive
  4. On peut chainer les appels et tester le résultat final uniquement sans avoir à tester les nodes intermédiaires
    pugi::xml_node bind = config.child(L"player").child(L"bind");
     if(!bind){
     return false;
    }

    (ne plantera pas même s’il n’a pas trouvé « player » !)

  5. Quelques fonctions utiles comme as_bool(), as_int(), as_float()..
  6. Support de XPath
  7. Support de l’unicode
  8. ….

Bref l’essayer c’est l’adopter !

How to safely convert a wide string into a narrow string (and vice-versa) ?

Irrlicht relies on wide strings (irr::core::stringw / std::wstring) for the GUI system but I had to convert some of them into narrow strings (std::string for instance) for the game.
So I looked on the internet for various solutions but there didn’t seem to be a general and clean one. Snippets did always call a fixed-size buffer which I din’t want to resort to.
That’s when I discovered this very neat C++ project (just a few headers). It makes the conversion through iterators and seems robust (until now I haven’t met any problem).

Here is the code I use :

inline void
convertIntoNarrowString(const std::wstring& original, std::string& converted)
{
utf8::utf16to8(original.begin(),original.end(), std::back_inserter(converted) );
}

inline void
convertIntoWideString(const std::string& original, std::wstring& converted)
{
utf8::utf8to16(original.begin(),original.end(), std::back_inserter(converted) );
}