J'ai découvert une incohérence troublante entre std::string
et les littéraux de chaîne en C++0x :
#include <iostream>
#include <string>
int main()
{
int i = 0;
for (auto e : "hello")
++i;
std::cout << "Number of elements: " << i << '\n';
i = 0;
for (auto e : std::string("hello"))
++i;
std::cout << "Number of elements: " << i << '\n';
return 0;
}
La sortie est :
Number of elements: 6
Number of elements: 5
Je comprends pourquoi cela se produit : la chaîne littérale est en fait un tableau de caractères qui inclut le caractère nul, et lorsque la boucle for basée sur l'intervalle appelle std::end()
sur le tableau de caractères, il obtient un pointeur au-delà de la fin du tableau ; puisque le caractère nul fait partie du tableau, il obtient donc un pointeur au-delà du caractère nul.
Cependant, je pense que cela est très peu souhaitable : sûrement std::string
et les chaînes de caractères doivent se comporter de la même manière lorsqu'il s'agit de propriétés aussi élémentaires que leur longueur ?
Existe-t-il un moyen de résoudre cette incohérence ? Par exemple, est-ce que std::begin()
y std::end()
soit surchargé pour les tableaux de caractères de façon à ce que la plage qu'ils délimitent n'inclue pas le caractère nul de fin ? Dans l'affirmative, pourquoi cela n'a-t-il pas été fait ?
EDIT : Pour justifier un peu plus mon indignation à ceux qui ont dit que je ne fais que subir les conséquences de l'utilisation de chaînes de style C qui sont une "fonctionnalité héritée", considérez un code comme le suivant :
template <typename Range>
void f(Range&& r)
{
for (auto e : r)
{
...
}
}
Vous attendriez-vous f("hello")
y f(std::string("hello"))
de faire quelque chose de différent ?