web-dev-qa-db-fra.com

Pourquoi C ++ interdit-il les structures anonymes?

Certains compilateurs C++ autorisent les unions et structures anonymes comme une extension du C++ standard. C'est un peu de sucre syntaxique qui est parfois très utile.

Quelle est la justification qui empêche que cela fasse partie de la norme? Y a-t-il un barrage technique? Une question philosophique? Ou tout simplement pas assez d'un besoin pour le justifier?

Voici un exemple de ce dont je parle:

struct vector3 {
  union {
    struct {
      float x;
      float y;
      float z;
    };
    float v[3];
  };
};

Mon compilateur acceptera cela, mais il avertit que "struct/union sans nom" est une extension non standard de C++ .

85
Adrian McCarthy

Comme d'autres l'ont souligné, les unions anonymes sont autorisées dans le C++ standard, mais les structures anonymes ne le sont pas.

La raison en est que C prend en charge les unions anonymes mais pas les structures anonymes *, donc C++ prend en charge les premières pour la compatibilité mais pas les dernières car elles ne sont pas nécessaires pour la compatibilité.

De plus, les structures anonymes en C++ ne sont pas très utiles. L'utilisation que vous démontrez, pour avoir une structure contenant trois flottants qui peuvent être référencés soit par .v[i], ou .x, .y, et .z, Je crois que cela entraîne un comportement indéfini en C++. C++ ne vous permet pas d'écrire à un membre d'une union, par exemple .v[1], puis lisez à partir d'un autre membre, dites .y. Bien que le code qui le fasse ne soit pas rare, il n'est pas réellement bien défini.

Les fonctionnalités de C++ pour les types définis par l'utilisateur fournissent des solutions alternatives. Par exemple:

struct vector3 {
  float v[3];
  float &operator[] (int i) { return v[i]; }
  float &x() { return v[0]; }
  float &y() { return v[1]; }
  float &z() { return v[2]; }
};

* C11 ajoute apparemment des structures anonymes, donc une future révision de C++ pourrait les ajouter.

43
bames53

Je dirai que vous pouvez nettoyer votre vector3 déclaration en utilisant simplement un union

union vector3 {
  struct { float x, y, z; } ;
  float v[3] ;
} ;

Bien sûr, les structures anonymes étaient une extension MSVC . Mais ISO C11 le permet maintenant, et gcc le permet , tout comme le compilateur llvm d'Apple.

Pourquoi en C11 et non en C++ 11? Je ne suis pas sûr, mais pratiquement parlant (gcc ++, MSVC++ et le compilateur C++ d'Apple) les compilateurs C++ les prennent en charge.

20
bobobobo

Pas sûr de ce que vous voulez dire. Section 9.5 de la spécification C++, clause 2:

Une union de la forme

union { member-specification } ;

est appelé un syndicat anonyme; il définit un objet sans nom de type sans nom.

Vous pouvez aussi faire des choses comme ça:

void foo()
{
  typedef
  struct { // unnamed, is that what you mean by anonymous?
    int a;
    char b;
  } MyStructType; // this is more of a "C" style, but valid C++ nonetheless

  struct { // an anonymous struct, not even typedef'd
    double x;
    double y;
  } point = { 1.0, 3.4 };
}

Pas toujours très utile ... bien que parfois utile dans de mauvaises définitions de macro.

6
Dan

Les syndicats peuvent être anonymes; voir la norme, 9.5, paragraphe 2.

Quel objectif voyez-vous qu'une structure ou une classe anonyme remplit? Avant de spéculer pourquoi quelque chose n'est pas dans la norme, j'aimerais avoir une idée de pourquoi cela devrait être, et je ne vois pas l'utilité d'une structure anonyme.

0
David Thornley

Sur la base de l'édition, des commentaires et de cet article MSDN: Structures anonymes , je vais hasarder une supposition - cela correspond mal au concept d'encapsulation. Je ne m'attendrais pas à ce qu'un membre d'une classe dérange mon espace de noms de classe au-delà de l'ajout d'un seul membre. De plus, les modifications apportées à la structure anonyme peuvent affecter ma classe sans autorisation.

0
JonM

Votre code

union {
  struct {
    float x;
    float y;
    float z;
  };
  float v[3];
};

est comme

union Foo {
   int;
   float v[3];
};

ce qui est sûrement invalide (en C99 et avant).

La raison en est probablement pour simplifier l'analyse (en C), car dans ce cas, il vous suffit de vérifier que le corps struct/union n'a que des "déclarations de déclaration" " comme

Type field;

Cela dit, gcc et "autres compilateurs" prend en charge les champs sans nom en tant qu'extension.

Edit: Les structures anonymes sont désormais officiellement supportées en C11 (§6.7.2.1/13).

0
kennytm