web-dev-qa-db-fra.com

Déclarer une variable de deux types: "int char"

Je suis un débutant en C++ et je lis Programmation de Bjarne Stroustrup: principes et pratique utilisant le C++.

Dans la section sur .9.2 Conversions non sécurisées, l’auteur a mentionné

Lorsque l'initialiseur est un littéral entier, le compilateur peut vérifier la valeur réelle et accepter les valeurs n'impliquant pas un rétrécissement:

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

Je suis perplexe par cette déclaration. Il utilise deux types (int et char). Je n'ai jamais vu une telle déclaration dans Java et Swift (les deux langages que je connais assez bien). Est-ce une faute de frappe ou une syntaxe C++ valide?

80
Thor

C'est une erreur dans le livre. Ce n'est pas une déclaration C++ valide, même sans la supposée conversion restrictive.

Cela n'est mentionné dans aucune des erratas sur page de Bjarne Stroustrup (4ème impression et antérieure), ce qui est étrange. C'est une erreur assez claire. J'imagine que c'est commenté avec //error peu de gens remarquent l'erreur dans la déclaration elle-même.

94
StoryTeller

Le livre est faux.

La séquence de jetons int char b1{1000}; n'est pas sémantiquement valide en C++.

Vous essayez de déclarer b1 avec plusieurs types, ce qui n’a aucun sens.

23
Bathsheba

Il est faux. En C/C++, les déclarations multi-types peuvent être réalisées via l'utilisation de unions. Par exemple:

union {
    int i;
    char c;
} var;

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

Le stockage est le même, donc .c et .i ne sont que des poignées par type ayant la même valeur.

10
Alex

Ceci est faux dans la syntaxe C/C++. En plus de unions (voir @Alex answer), il existe un moyen C++ de ne stocker qu'un seul des types disponibles appelé std::variant (type-safe union):

_#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
}
_
6
val