Почему C ++ запрещает анонимные структуры? - PullRequest
83 голосов
/ 12 февраля 2010

Некоторые компиляторы C ++ допускают анонимные объединения и являются расширением стандарта C ++. Это немного синтаксического сахара, который иногда очень полезен.

Какое обоснование препятствует тому, чтобы это стало частью стандарта? Есть ли технический барьер? Философский? Или просто не хватает необходимости оправдывать это?

Вот пример того, о чем я говорю:

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

Мой компилятор примет это, но предупреждает, что "безымянная структура / объединение" является нестандартным расширением C ++ .

Ответы [ 6 ]

42 голосов
/ 08 октября 2012

Как отмечали другие, анонимные объединения разрешены в стандарте C ++, но анонимные структуры - нет.

Причина этого в том, что C поддерживает анонимные объединения, но не анонимные структуры *, поэтому C ++ поддерживает первое для совместимости, но не второе, потому что оно не требуется для совместимости.

Кроме того, анонимные структуры в C ++ не слишком полезны. Использование, которое вы демонстрируете, чтобы иметь структуру, содержащую три числа с плавающей точкой, на которые могут ссылаться либо .v[i], либо .x, .y и .z, я считаю, приводит к неопределенному поведению в C ++. C ++ не позволяет вам писать одному члену объединения, скажем .v[1], а затем читать другому члену, скажем .y. Хотя код, который делает это, не редкость, на самом деле он не очень хорошо определен.

Средства C ++ для пользовательских типов предоставляют альтернативные решения. Например:

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, очевидно, добавляет анонимные структуры, поэтому в будущем C ++ может добавить их.

20 голосов
/ 15 октября 2012

Я скажу, что вы можете очистить вашу декларацию vector3, просто используя union

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

Конечно, анонимные структуры были расширением MSVC . Но ISO C11 разрешает это сейчас, и gcc разрешает это , как и компилятор Apple llvm.

Почему в C11, а не в C ++ 11? Я не уверен, но практически большинство (gcc ++, MSVC ++ и Apple C ++ компилятор) компиляторов их поддерживают.

7 голосов
/ 12 февраля 2010

Не уверен, что вы имеете в виду. Раздел 9.5 спецификации C ++, пункт 2:

Объединение формы

union { member-specification } ;

называется анонимным союзом; он определяет безымянный объект безымянного типа.

Вы тоже можете делать такие вещи:

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 };
}

Не всегда очень полезно ... хотя иногда полезно в грязных определениях макросов.

1 голос
/ 13 февраля 2010

Основываясь на редактировании, комментариях и статье MSDN: Анонимные структуры , я рискну догадаться - это плохо согласуется с концепцией инкапсуляции.Я не ожидал бы, что член класса будет связываться с моим пространством имен класса, кроме простого добавления одного члена.Кроме того, изменения в анонимной структуре могут повлиять на мой класс без разрешения.

1 голос
/ 13 февраля 2010

Ваш код

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

похоже на

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

, что, безусловно, недопустимо (в C99 и ранее).

Причина в том, что вероятно упрощает синтаксический анализ (в C), потому что в этом случае вам нужно только проверить, что тело struct / union имеет только "операторы объявления", такие как

Type field;

Тем не менее, gcc и "другие компиляторы" поддерживают неназванные поля в качестве расширения.

Редактировать: Анонимные структуры теперь официально поддерживаются в C11 (§6.7.2.1 / 13).

1 голос
/ 12 февраля 2010

Союзы могут быть анонимными; см. Стандарт, 9.5, параграф 2.

Какую цель вы видите для анонимной структуры или класса? Прежде чем размышлять о том, почему что-то отсутствует в Стандарте, я хотел бы иметь некоторое представление о том, почему это должно быть, и я не вижу использования анонимной структуры.

...