Perché non c'è std :: stou?


96

C ++ 11 ha aggiunto alcune nuove funzioni di conversione delle stringhe:

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

Include stoi (string to int), stol (string to long), stoll (string to long long), stoul (string to unsigned long), stoull (string to unsigned long long). Notevole in sua assenza è una funzione stou (string to unsigned). C'è qualche motivo per cui non è necessario, ma tutti gli altri lo sono?

correlate: Nessuna funzione "sto {short, unsigned short}" in C ++ 11?


6
La mia domanda intendeva essere più sulla falsariga di "c'è qualche inconveniente non ovvio di usare solo stoul". Ovviamente questo creerà problemi con l'istanza del modello, ma c'è qualcos'altro che non sto considerando? Commenti sul motivo per cui è stato omesso sarebbero carini ma secondari.
David Stone

12
@NicolBolas Non riesco a capire perché questo non sia costruttivo. È una domanda perfettamente valida in quanto non riesco a vedere alcuna ragione per questa incoerenza e le risposte possono fornire intuizioni su alcune possibili ragioni valide ma non così ovvie per questo.
Christian Rau

4
@SethCarnegie Bene, quello che fa la tua piattaforma (e forse la maggior parte delle piattaforme) è semplicemente irrilevante, perché unsigned longsemplicemente no unsigned int.
Christian Rau

4
@SethCarnegie: sul mio computer tipico, unsigned longè di 64 bit e unsigned int32. Sono di tipi diversi e non si può presumere che siano uguali tra loro.
Mike Seymour

2
@NicolBolas Come detto, l'OP (e io) non sappiamo che è speculativo, in quanto potrebbe esserci una ragione valida e perfetta per essere sepolto in profondità negli interni del linguaggio C ++. Ma dal momento che dici che è speculativo, immagino che non ci sia tale ragione. Ma ancora una volta, forse una persona responsabile di C ++ 11 può ancora rispondere. Questa non è stouuna domanda "Wah wah, dov'è quella dannata ", ma una domanda che chiede una ragione forse definita per questa ovvia incoerenza. Se sai che non esiste un motivo del genere, allora pubblicalo come risposta.
Christian Rau

Risposte:


29

La risposta più semplice sarebbe che la libreria C non ha un " strtou" corrispondente e le funzioni stringa C ++ 11 sono solo involucri sottilmente velati attorno alle funzioni della libreria C: le std::sto*funzioni rispecchiano strto*e le std::to_stringfunzioni usano sprintf.


Modifica: come sottolinea KennyTM, entrambi stoie vengono stolutilizzati strtolcome funzione di conversione sottostante, ma è ancora misterioso il motivo per cui mentre esiste stoulche utilizza strtoul, non vi è alcuna corrispondenza stou.


14
Sai perché il Comitato C ++ ha deciso di adottare un tale approccio C-ish? Qualcosa di simile boost::lexical_cast<>()sembra un modo più C ++ di fare le cose.
Paul Manta

2
Questi dettagli di implementazione sono davvero definiti da standard?
Gare di leggerezza in orbita il

4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Effetti: le prime due funzioni chiamano strtol (str.c_str (), ptr, base) e le ultime tre funzioni chiamano strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) e strtoull (str.c_str (), ptr, base), rispettivamente.
Mike Seymour

12
Non importa se lo standard C ++ dice "deve essere implementato chiamando ...", perché lo standard C ++ ha ancora la regola globale as-if: se lo standard dice che std::sto*deve essere implementato come wrapper per le funzioni della libreria C, e un programma valido non può dire che non sono implementati segretamente in modo diverso, l'implementazione è valida.

2
Completamente fuori tema, penso che le ragioni pratiche per non usare iostream come Boost / lexical_cast siano le prestazioni pure; Credo che iostream perdano contro strtoul ecc. Con un margine considerevole.
Kerrek SB

22

Non ho idea del perché stoiesista ma no stou, ma l'unica differenza tra stoule un ipotetico stousarebbe un controllo che il risultato sia nell'intervallo di 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;
}

(Allo stesso modo, stoiè anche simile a stol, solo con un controllo di intervallo diverso; ma poiché esiste già, non è necessario preoccuparsi di come implementarlo esattamente.)


La differenza tra stoie stol, o stole stollè anche solo un controllo dell'intervallo.
Hossein

1
@ Hossein: tra stoie stol, sì. Ma stole stollnon differiscono solo nel controllo dell'intervallo, chiamano diverse funzioni di libreria.
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'utilizzo di maschere per eseguire questa operazione con la dimensione del valore prevista in bit espressa nella maschera, renderà questo lavoro per i long a 64 bit rispetto agli int a 32 bit, ma anche per i long a 32 bit rispetto agli int a 32 bit.

Nel caso di 64 bit long, ~ 0xffffffffl diventerà 0xffffffff00000000 e quindi vedrà se uno dei primi 32 bit è impostato. Con i long a 32 bit, ~ 0xffffffffl diventa 0x00000000 e il controllo della maschera sarà sempre zero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.