Le C++ est un langage très sympa qui permet de faire de l'objet tout en gardant une compatibilité avec le C. Il est de fait le langage le plus approprié lorsqu'on veut allier objet et "bas niveau". Cependant, il possède des défauts assez décevants car pouvant être (je pense) évités.
Je vais débuter une série d'articles concernant les quelques inconvénients que je rencontre au quotidien. Si bien évidemment pour vous c'est une "feature not a bug", n'hésitez pas à exprimer votre pensée dans les commentaires.
std::string non généralisé
Quelque chose de très chiant que je rencontre fréquemment en C++, c'est le fait que l'objet std::string n'est pas utilisée tout le temps, même dans la STL. Bien évidemment, on serait tenté de réagir en disant qu'il y a des moments où ça n'est pas nécessaire, quand on veut accélerer les opérations ou faire du bas niveau.
Oui mais dans le cas suivant je trouve ça quand même dommage d'avoir à écrire :
std::ifstream fp(filename.c_str());
Le constructeur de cette classe, dont but est l'ouverture d'un fichier en écriture, ne prend qu'un const char* et même pas un std::string.
Vous allez me dire que ça ne change rien, si ce n'était pas moi qui appellait la méthode c_str() c'est lui qui le ferait. Certes. Sauf que je trouve ça incroyablement laid de devoir faire appel à ces méthodes dans mon code. Le but de la STL est d'encapsuler du code de bas niveau dans des objets.
Il est navrant je trouve même que l'on ait, dans le cas d'une utilisation haut niveau, à savoir qu'un std::string encapsule un char[]. L'utilisation de c_str() devrait être réservée lorsque l'on souhaite faire du bas niveau (sockets par exemple).
Le pire dans cet exemple c'est qu'un simple constructeur de trois lignes auraient pu régler ce problème.
Conversation std::string <-> int
Il n'existe pas, à l'instar des autres langages objet de haut niveau, une méthode .toint() ou similaire, à l'objet std::string. Le seul moyen de convertir une chaîne en entier est :
int i; std::string str = "123"; std::istringstream s(str); s >> i;
Et d'un entier en une chaîne :
std::ostringstream s; std::string str; int i = 123; s << i; str = s.str()
C'est très peu pratique, et en général dans mes projets C++ je me défini les deux fonctions templates ci-dessous :
template<typename T> T StrToTyp(const std::string& str) { T dest; std::istringstream iss( str ); iss >> dest; return dest; } template<typename T> std::string TypToStr(const T& value) { std::ostringstream oss; oss << value; return oss.str(); }
À utiliser de la manière suivante :
int i = 123; std::string s; s = TypToStr(i); i = StrToTyp<int>(s);
L'avantage est que ce template permet de convertir de et vers tous les types pris en charge par les objets std::ostringstream et std::istringstream
Sinon, pourquoi pas étendre la STL en utilisant une classe string perso, qui hériterait de std::string ?
Dériver la classe std::string pourrait être une bonne idée (meilleurs en tous cas que les extensions C#), cela dit il faut voir jusqu’où ça ne pose pas problème (que ça reste transparent pour l’utilisation).