Pourquoi n'y a-t-il pas de std :: stou?

96

C ++ 11 a ajouté de nouvelles fonctions de conversion de chaîne:

http://en.cppreference.com/w/cpp/string/basic_string/stoul

Il inclut stoi (chaîne en entier), stol (chaîne en long), stoll (chaîne en long long), stoul (chaîne en long non signé), stoull (chaîne en long non signé). Notable en son absence est une fonction stou (chaîne non signée). Y a-t-il une raison pour laquelle ce n'est pas nécessaire, mais toutes les autres le sont?

Related: Pas de fonctions "sto {short, unsigned short}" dans C ++ 11?

David Stone
la source
6
Ma question visait à être davantage du type "y a-t-il un inconvénient non évident à utiliser simplement stoul". Évidemment, cela va gâcher l'instanciation du modèle, mais y a-t-il autre chose que je ne considère pas? Les commentaires sur les raisons pour lesquelles il a été laissé de côté seraient bien mais secondaires.
David Stone
12
@NicolBolas Je ne vois pas pourquoi ce n'est pas constructif. C'est une question parfaitement valable car je ne vois aucune raison à cette incohérence et des réponses peuvent donner un aperçu de certaines raisons valables éventuellement existantes mais pas évidentes.
Christian Rau
4
@SethCarnegie Eh bien, ce que fait votre plate-forme (et peut-être la majorité des plates-formes) n'est tout simplement pas pertinent, car un unsigned longtout est non unsigned int.
Christian Rau
4
@SethCarnegie: sur mon ordinateur typique, unsigned longc'est 64 bits et unsigned int32. Ils sont de types différents et ne peuvent pas être supposés être identiques les uns aux autres.
Mike Seymour
2
@NicolBolas Comme dit, l'OP (et moi) ne savons pas que c'est spéculatif, car il pourrait juste y avoir une raison valable parfaite pour que cela soit enfoui profondément dans le langage interne de C ++. Mais puisque vous dites que c'est spéculatif, je suppose qu'il n'y a pas de telle raison. Mais encore une fois, peut-être qu'une personne responsable de C ++ 11 peut toujours y répondre. Ce n'est pas une question "Wah wah, où est ce foutu stou" -question, mais une question demandant une raison peut-être définie pour cette incohérence évidente. Si vous savez qu'il n'y a pas de telle raison, alors postez-la comme réponse.
Christian Rau

Réponses:

29

La réponse la plus évidente serait que la bibliothèque C n'a pas de « strtou» correspondant , et les fonctions de chaîne C ++ 11 ne sont que des enveloppes finement voilées autour des fonctions de la bibliothèque C: les std::sto*fonctions miroir strto*et les std::to_stringfonctions utilisent sprintf.


Edit: Comme le souligne KennyTM, les deux stoiet l' stolutilisent strtolcomme fonction de conversion sous-jacente, mais il est encore mystérieux de savoir pourquoi tant qu'il existe des stoulutilisations strtoul, il n'y a pas de correspondance stou.

Kerrek SB
la source
14
Savez-vous pourquoi le comité C ++ a décidé d'opter pour une telle approche C-ish? Quelque chose comme cela boost::lexical_cast<>()semble être une façon plus C ++ de faire les choses.
Paul Manta
2
Ces détails d'implémentation sont-ils vraiment définis de manière standard?
Courses de légèreté en orbite le
4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Effets: les deux premières fonctions appellent strtol (str.c_str (), ptr, base), et les trois dernières fonctions appellent strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) et strtoull (str.c_str (), ptr, base), respectivement.
Mike Seymour
12
Peu importe si le standard C ++ dit "doit être implémenté en appelant ...", car le standard C ++ a toujours la règle globale comme si: si le standard dit std::sto*doit être implémenté comme wrappers pour les fonctions de la bibliothèque C, et un programme valide ne peut pas dire qu'ils ne sont pas secrètement implémentés différemment, l'implémentation est valide.
2
Complètement hors sujet, je pense que les raisons pratiques de ne pas utiliser iostreams comme Boost / lexical_cast le font, c'est la pure performance; Je crois que les iostreams perdent contre strtoul etc. par une marge considérable.
Kerrek SB
22

Je ne sais pas pourquoi stoiexiste mais pas stou, mais la seule différence entre stoulet une hypothétique stouserait de vérifier que le résultat est dans la plage de unsigned:

unsigned stou(std::string const & str, size_t * idx = 0, int base = 10) {
    unsigned long result = std::stoul(str, idx, base);
    if (result > std::numeric_limits<unsigned>::max()) {
        throw std::out_of_range("stou");
    }
    return result;
}

(De même, stoiest également similaire à stol, juste avec une vérification de plage différente; mais comme il existe déjà, il n'est pas nécessaire de s'inquiéter de la manière exacte de l'implémenter.)

Mike Seymour
la source
La différence entre stoiet stol, ou stolet stolln'est également qu'une vérification de plage.
Hossein
1
@Hossein: Entre stoiet stol, oui. Mais stolet stollne diffèrent pas seulement dans le contrôle de plage, ils appellent différentes fonctions de bibliothèque.
Ben Voigt
0
unsigned long ulval = std::stoul(buf);
unsigned long mask = ~0xffffffffl;
unsigned int uival;
if( (ulval & mask) == 0 )
    uival = (unsigned int)ulval;
else {
    ...range error...
}

L'utilisation de masques pour ce faire avec la taille de la valeur attendue en bits exprimée dans le masque fera que cela fonctionnera pour les entiers 64 bits par rapport aux entiers 32 bits, mais aussi pour les entiers 32 bits et 32 ​​bits.

Dans le cas de longs 64 bits, ~ 0xffffffffl deviendra 0xffffffff00000000 et verra donc si l'un des 32 premiers bits est défini. Avec des longs 32 bits, ~ 0xffffffffl devient 0x00000000 et la vérification du masque sera toujours zéro.

Gregg merveilleusement
la source