¿Por qué no hay std :: stou?

96

C ++ 11 agregó algunas funciones nuevas de conversión de cadenas:

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

Incluye stoi (cadena a int), stol (cadena a largo), stoll (cadena a largo largo), stoul (cadena a unsigned long), stoull (cadena a unsigned long long). Notable en su ausencia es una función stou (cadena a unsigned). ¿Hay alguna razón por la que no es necesario, pero todos los demás lo son?

relacionado: ¿ No hay funciones "sto {short, unsigned short}" en C ++ 11?

David Stone
fuente
6
Mi pregunta tenía la intención de ser más en la línea de "¿hay algún inconveniente no obvio de usar stoul?". Obviamente, eso interferirá con la creación de instancias de plantillas, pero ¿hay algo más que no esté considerando? Los comentarios sobre por qué se omitió serían agradables pero secundarios.
David Stone
12
@NicolBolas No puedo ver por qué esto no es constructivo. Es una pregunta perfectamente válida, ya que no veo ninguna razón para esta inconsistencia y las respuestas pueden dar una idea de alguna razón válida posiblemente existente pero no tan obvia para ello.
Christian Rau
4
@SethCarnegie Bueno, lo que hace su plataforma (y tal vez la mayoría de las plataformas) es simplemente irrelevante, porque unsigned longsimplemente es no unsigned int.
Christian Rau
4
@SethCarnegie: en mi computadora típica, unsigned longes de 64 bits y unsigned int32. Son de diferentes tipos y no se puede suponer que sean iguales entre sí.
Mike Seymour
2
@NicolBolas Como se dijo, el OP (y yo) no sabemos que es especulativo, ya que podría haber una razón válida perfecta para que esté enterrado en lo profundo del lenguaje interno de C ++. Pero como dices que es especulativo, supongo que no existe tal razón. Pero nuevamente, tal vez una persona responsable de C ++ 11 aún pueda responderla. Esta no es stouuna pregunta de "Wah wah, ¿dónde está esa maldita? ", Sino una pregunta que busca una razón posiblemente definida de esta obvia inconsistencia. Si sabe que no existe tal razón, entonces publíquelo como una respuesta.
Christian Rau

Respuestas:

29

La respuesta más acertada sería que la biblioteca C no tiene un " strtou" correspondiente , y las funciones de cadena de C ++ 11 son sólo envoltorios finos alrededor de las funciones de la biblioteca C: las std::sto*funciones reflejan strto*y las std::to_stringfunciones usan sprintf.


Editar: Como señala Kenny TM, ambos stoiy el stoluso strtolcomo la función de conversión subyacente, pero aún es misterioso por qué, si bien existe stoulese uso strtoul, no hay correspondencia stou.

Kerrek SB
fuente
14
¿Sabes por qué el Comité de C ++ decidió optar por un enfoque tan C-ish? Algo así boost::lexical_cast<>()parece una forma más de C ++ de hacer las cosas.
Paul Manta
2
¿Estos detalles de implementación están realmente definidos por estándares?
Lightness Races in Orbit
4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Efectos: las dos primeras funciones llaman a strtol (str.c_str (), ptr, base), y las últimas tres funciones llaman a strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) y strtoull (str.c_str (), ptr, base), respectivamente.
Mike Seymour
12
No importa si el estándar C ++ dice "debe implementarse llamando a ...", porque el estándar C ++ todavía tiene la regla global como si: si el estándar dice que std::sto*deben implementarse como envoltorios para las funciones de la biblioteca C, y un programa válido no puede decir que no se implementan en secreto de manera diferente, la implementación es válida.
2
Completamente fuera de tema, creo que las razones prácticas para no usar iostreams como lo hace Boost / lexical_cast es puro rendimiento; Creo que los iostreams pierden contra strtoul, etc. por un margen considerable.
Kerrek SB
22

No tengo idea de por qué stoiexiste, pero no stou, pero la única diferencia entre stouly un hipotético stousería comprobar que el resultado está en el rango 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;
}

(Del mismo modo, stoitambién es similar a stol, solo con una verificación de rango diferente; pero como ya existe, no hay necesidad de preocuparse por cómo implementarlo exactamente).

Mike Seymour
fuente
La diferencia entre stoiy stol, o stoly stolltambién es solo una verificación de rango.
Hossein
1
@Hossein: Entre stoiy stol, sí. Pero stoly stollno solo difieren en la verificación de rango, sino que llaman a diferentes funciones de biblioteca.
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...
}

El uso de máscaras para hacer esto con el tamaño del valor esperado en bits expresado en la máscara hará que esto funcione para longs de 64 bits frente a entradas de 32 bits, pero también para entradas largas de 32 bits frente a entradas de 32 bits.

En el caso de longs de 64 bits, ~ 0xffffffffl se convertirá en 0xffffffff00000000 y, por lo tanto, verá si alguno de los 32 bits principales está configurado. Con longs de 32 bits, ~ 0xffffffffl se convierte en 0x00000000 y la comprobación de la máscara siempre será cero.

Gregg Wonderly
fuente