Declarar una variable con dos tipos: "int char"

81

Soy un principiante de C ++ y estoy leyendo Programación de Bjarne Stroustrup: Principios y práctica con C ++ .

En la sección sobre 3.9.2 Conversiones inseguras , el autor mencionó

Cuando el inicializador es un literal entero, el compilador puede verificar el valor real y aceptar valores que no impliquen un estrechamiento:

int char b1 {1000};     // error: narrowing (assuming 8-bit chars)

Estoy desconcertado por esta declaración. Utiliza dos tipos ( inty char). Nunca antes había visto tal declaración en Java y Swift (los dos lenguajes con los que estoy relativamente familiarizado). ¿Es esto un error tipográfico o una sintaxis válida de C ++?

Thor
fuente
2
¿Qué edición e impresión del libro tienes? ¿Ha buscado una errata del libro?
Un tipo programador
2
Entonces, ¿qué versión estás leyendo? Estoy seguro de que a Bjarne le gustaría saber sobre este error.
StoryTeller - Unslander Monica
1
3.9.2 Conversiones inseguras Por conversión insegura queremos decir que un valor puede convertirse implícitamente en un valor de otro tipo que no es igual al valor original. por ejemplo: int i = 20000; char c = i; Estas conversiones se denominan conversiones de "reducción". double to int, char o bool int to char o bool char to bool
Marichyasana
15
El float charotro tipo útil, especialmente en piscinas. Algunos vienen con un soporte para una cerveza.
Yakk - Adam Nevraumont
1
¿Es esto un error tipográfico o una sintaxis válida de C ++? Pruébelo (OK, OK, no, no es válido).
Paul Sanders

Respuestas:

95

Es un error del libro. Esa no es una declaración válida de C ++, incluso sin la supuesta conversión de restricción.

Sin embargo, no se menciona en ninguna de las erratas en la página de Bjarne Stroustrup (cuarta impresión y anteriores), lo cual es extraño. Es un error bastante claro. Me imagino que como está comentado //errorpocas personas notan el error en la propia declaración.

StoryTeller - Unslander Monica
fuente
¿Cuál fue probablemente el ejemplo de código previsto en el libro?
Pedro A
8
@Hamsterrific char b1 {1000};(porque eso provocaría el error mencionado en el comentario). Supongo que los dedos de Bjarne estaban cansados ​​ese día.
Paul Sanders
1
@PaulSanders ¿Cansado? ¡Escribió un extra intallí! :-)
Leo Heinsaar
1
@ LeoHeinsaar Lol. Bueno, entonces demasiado café :) O tal vez tartamudea :)
Paul Sanders
Sí: dedos cansados. Parece un error de cortar y pegar del ejemplo que lo precede. En ese ejemplo anterior, da dos líneas: int a {1000}; // OK [\ n] char b {a} // error: int -> char podría estrechar [\ n] y parece haber cortado y pegado ese ejemplo para el siguiente y no borró la parte "int" : int char b1 {1000}; // error: estrechamiento (asumiendo caracteres de 8 bits) [\ n] char b2 {48}; // OK [\ n]
L. Scott Johnson
24

El libro está mal.

La secuencia de tokens int char b1{1000};no es C ++ semánticamente válida.

Está intentando declarar b1con más de un tipo, lo que no tiene sentido.

Betsabé
fuente
10

Está mal. En C / C ++, las declaraciones de varios tipos se pueden lograr mediante el uso de uniones. P.ej:

union {
    int i;
    char c;
} var;

var.i = 42;
/* OR */
var.c = ‘c’;

El almacenamiento es el mismo, por lo que .cy .i son identificadores por tipo con el mismo valor.

Alex
fuente
6

Esto está mal en la sintaxis de C / C ++. Además de unions (consulte la respuesta de @Alex), hay una forma en C ++ de almacenar solo uno de los tipos disponibles llamado std::variant(unión segura de tipos ):

#include <variant>
#include <string>

int main()
{
    std::variant<int, float> v, w;
    v = 12; // v contains int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
      std::get<float>(w); // w contains int, not float: will throw
    }
    catch (std::bad_variant_access&) {}

    std::variant<std::string> v("abc"); // converting constructors work when unambiguous
    v = "def"; // converting assignment also works when unambiguous
}
val dice reinstalar a Monica
fuente