Dans la bibliothèque standard C ++, il existe des fonctions pour convertir des chaînes en types numériques:
stoi
stol
stoll
stoul
stoull
stof
stod
stold
mais je trouve fastidieux de les utiliser dans le code du modèle. Pourquoi il n'y a pas de fonctions de modèle comme:
template<typename T>
T sto(...)
convertir des chaînes en types numériques?
Je ne vois aucune raison technique de ne pas les avoir, mais peut-être que je manque quelque chose. Ils peuvent être spécialisés pour appeler les fonctions nommées sous-jacentes et utiliser enable_if
/ concepts
pour désactiver les types non numériques.
Existe-t-il des alternatives adaptées aux modèles dans la bibliothèque standard pour convertir la chaîne en types numériques et inversement de manière efficace?
c++
string-conversion
Mircea Ispas
la source
la source
Réponses:
C ++ 17 a une telle fonction générique chaîne à nombre, mais nommée différemment. Ils sont allés avec
std::from_chars
, qui est surchargé pour tous les types numériques.Comme vous pouvez le voir, la première surcharge prend tout type entier comme paramètre de sortie et lui attribuera la valeur si possible.
Il peut être utilisé comme ceci:
Comme vous pouvez le voir, cela peut fonctionner dans un contexte générique.
la source
Ce n'est pas un modèle, et cela ne fonctionne pas avec les locales mais si ce n'est pas un stop show alors C ++ 17 a déjà ce que vous voulez:
std::from_chars
Il y a des surcharges pour tous les types entiers et à virgule flottante et l'interface est la même, sauf pour les derniers paramètres qui sont respectivement différents pour les types entier et à virgule flottante (mais si la valeur par défaut est correcte, vous n'avez pas besoin de changer quoi que ce soit). Parce que ce n'est pas une fonction locale, elle est également assez rapide. Il va battre n'importe quelle autre chaîne pour convertir la fonction de valeur et généralement c'est par ordre de grandeur.
Il y a une très bonne vidéo CPPCON sur
<charconv>
(l'en-têtefrom_chars
habite) de Stephan T. Lavavej que vous pouvez regarder sur son utilisation et ses performances ici: https://www.youtube.com/watch?v=4P_kbF0EbZMla source
stoi
et ses amis (les conversions mentionnées dans la question) ne fonctionnent pas non plus avec les locales, donc ce n'est pas un showstopper.Vous ne gagneriez pas grand-chose car dans une expression comme
Il n'existe aucun moyen (facile) de déduire le type souhaité pour le paramètre de modèle. Il faudrait écrire
qui dans une certaine mesure va à l'encontre de l'objectif de fournir une fonction générique. D'un autre côté, un
serait d'une grande utilité comme vous vous en êtes rendu compte. En C ++ 17 il y en a
std::from_chars
, qui fait plus ou moins exactement cela (ce n'est pas un modèle mais un ensemble de surcharges et il prend des pointeurs vers des caractères au lieu d'une chaîne, mais ce ne sont que des détails mineurs).PS Il n'y a pas de moyen facile de déduire le type souhaité dans l'expression ci-dessus, mais il y en a un. Je ne pense pas que le cœur de votre question était exactement la signature que vous avez demandée, et je ne pense pas que ce qui suit est un bon moyen de le mettre en œuvre, mais je savais qu'il existe un moyen de faire la
int x = sto("1");
compilation ci-dessus et j'étais curieux de le voir en action.Cela fonctionne comme prévu, mais il présente de graves inconvénients, ce qui est peut-être le plus important, il permet d'écrire
auto x = sto(s);
, c'est-à-dire qu'il est facile à mal utiliser.la source
auto x = sto(s)
? Cette implémentation particulière se casse carconverter::x
est une référence qui sort du cadre, mais qui peut être réparée. Supprimez simplement la référence et utilisezstd::string
la sémantique de mouvement de.converter
, je ne sais pas non plus si l'utilisation d'un opérateur de conversion de modèle était le meilleur choix, des choses qui pourraient être corrigées. Peut-être que ce n'est pas si mal que je le pensais initialementLa solution compatible avec tous (même les compilateurs C ++ plus anciens comme C ++ - 98) consiste à utiliser boost :: lexical_cast qui est un modèle pour convertir entre les types numérique et chaîne dans les deux sens.
Exemple:
Voir: https://www.boost.org/doc/libs/1_42_0/libs/conversion/lexical_cast.htm
la source
Sur les anciennes versions C ++, stringstream est votre ami. Si je comprends bien, les éléments suivants pourraient vous intéresser. C'est C ++ 11.
https://wandbox.org/permlink/nUNiUwWWTr7a0NXM
Cette méthode fonctionne en C ++ 11 et est assez générale. D'après mon expérience, cette méthode est robuste, mais pas la plus performante.
la source