Warum gibt es kein std :: stou?

96

C ++ 11 hat einige neue Funktionen zur Konvertierung von Zeichenfolgen hinzugefügt:

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

Es umfasst stoi (string to int), stol (string to long), stoll (string to long long), stoul (string to unsigned long), stoull (string to unsigned long long). Bemerkenswert in seiner Abwesenheit ist eine stou-Funktion (Zeichenfolge zu vorzeichenlos). Gibt es einen Grund, warum es nicht benötigt wird, aber alle anderen?

Verwandte: Keine "sto {short, unsigned short}" -Funktionen in C ++ 11?

David Stone
quelle
6
Meine Frage sollte eher im Sinne von "Gibt es einen nicht offensichtlichen Nachteil, nur Stoul zu verwenden" sein. Das wird natürlich die Instanziierung von Vorlagen beeinträchtigen, aber gibt es noch etwas, das ich nicht in Betracht ziehe? Kommentare, warum es weggelassen wurde, wären nett, aber zweitrangig.
David Stone
12
@NicolBolas Ich kann nicht verstehen, warum dies nicht konstruktiv ist. Es ist eine vollkommen gültige Frage, da ich keinen Grund für diese Inkonsistenz sehe und Antworten möglicherweise Einblicke in einen möglicherweise existierenden gültigen, aber nicht diesen offensichtlichen Grund dafür geben.
Christian Rau
4
@ SethCarnegie Nun, was Ihre Plattform (und vielleicht die Mehrheit der Plattformen) tut, ist einfach irrelevant, weil ein unsigned longgerechtes Nein ist unsigned int.
Christian Rau
4
@ SethCarnegie: Auf meinem typischen Computer sind unsigned longes 64 Bit und unsigned int32. Es handelt sich um verschiedene Typen, von denen nicht angenommen werden kann, dass sie identisch sind.
Mike Seymour
2
@NicolBolas Wie gesagt, das OP (und ich) wissen nicht, dass es spekulativ ist, da es nur einen vollkommen gültigen Grund dafür geben könnte, dass es tief in den Sprachinternalen von C ++ vergraben ist. Aber da Sie sagen, dass es spekulativ ist, gibt es wohl keinen solchen Grund. Aber vielleicht kann eine C ++ 11-verantwortliche Person noch darauf antworten. Dies ist keine "Wah wah, wo ist diese verdammte stou" Frage, sondern eine Frage, die nach einem möglicherweise eindeutigen Grund für diese offensichtliche Inkonsistenz fragt. Wenn Sie wissen, dass es keinen solchen Grund gibt, posten Sie ihn als Antwort.
Christian Rau

Antworten:

29

Die beste Antwort wäre, dass die C-Bibliothek kein entsprechendes " strtou" hat und die C ++ 11-Zeichenfolgenfunktionen nur dünn verschleierte Wrapper um die C-Bibliotheksfunktionen sind: Die std::sto*Funktionen spiegeln strto*sich und die std::to_stringFunktionen werden verwendet sprintf.


Edit: Wie KennyTM weist darauf hin, beide stoiund stolVerwendung strtolals die zugrunde liegenden Umwandlungsfunktion, aber es ist immer noch mysteriös , warum während es existiert , stouldass Anwendungen strtoul, gibt es keine entsprechend stou.

Kerrek SB
quelle
14
Wissen Sie, warum sich das C ++ - Komitee für einen solchen C-ischen Ansatz entschieden hat? So etwas boost::lexical_cast<>()scheint eine eher C ++ - Methode zu sein.
Paul Manta
2
Sind diese Implementierungsdetails wirklich standarddefiniert?
Leichtigkeitsrennen im Orbit
4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Effekte: Die ersten beiden Funktionen rufen strtol (str.c_str (), ptr, base) und die letzten drei Funktionen strtoul (str.c_str (), ptr, base auf ), strtoll (str.c_str (), ptr, base) bzw. strtoull (str.c_str (), ptr, base).
Mike Seymour
12
Es spielt keine Rolle, ob der C ++ - Standard "muss durch Aufrufen implementiert werden ..." besagt, da der C ++ - Standard weiterhin die globale Als-ob-Regel enthält: Wenn der Standard sagt, std::sto*dass er als Wrapper für die C-Bibliotheksfunktionen implementiert werden muss, und Ein gültiges Programm kann nicht sagen, dass sie nicht heimlich anders implementiert sind. Die Implementierung ist gültig.
2
Völlig abseits des Themas denke ich, dass die praktischen Gründe dafür, dass iostreams nicht wie Boost / lexical_cast verwendet werden, reine Leistung sind. Ich glaube, dass iostreams gegen strtoul etc. mit erheblichem Abstand verlieren.
Kerrek SB
22

Ich habe keine Ahnung, warum es stoiexistiert, aber nicht stou, aber der einzige Unterschied zwischen stoulund einer Hypothese stouwäre eine Überprüfung, ob das Ergebnis im Bereich von 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;
}

(Ebenso stoiist es ähnlich stol, nur mit einer anderen Bereichsprüfung; aber da es bereits existiert, müssen Sie sich keine Gedanken darüber machen, wie es genau implementiert werden soll.)

Mike Seymour
quelle
Der Unterschied zwischen stoiund stol, oder stolund stollist auch nur eine Bereichsprüfung.
Hossein
1
@Hossein: Zwischen stoiund stolja. Aber stolund stollunterscheiden sich nicht nur in Bereichsprüfung, sie verschiedene Bibliotheksfunktionen aufrufen.
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...
}

Wenn Sie Masken verwenden, um dies mit der erwarteten Wertgröße in den in der Maske ausgedrückten Bits zu tun, funktioniert dies für 64-Bit-Longs gegenüber 32-Bit-Ints, aber auch für 32-Bit-Longs gegenüber 32-Bit-Ints.

Bei 64-Bit-Longs wird ~ 0xffffffffl zu 0xffffffff00000000 und prüft somit, ob eines der oberen 32 Bits gesetzt ist. Bei 32-Bit-Longs wird ~ 0xffffffffl zu 0x00000000 und die Maskenprüfung ist immer Null.

Gregg Wunderbar
quelle