Почему С++ запрещает анонимные структуры?

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

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

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

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

Мой компилятор примет это, но он предупреждает, что "nameless struct/union" является нестандартным расширением для С++.

Ответ 1

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

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

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

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

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

Ответ 2

Я скажу, вы можете очистить объявление vector3, просто используя union

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

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

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

Ответ 3

Не уверен, что вы имеете в виду. Раздел 9.5 спецификации С++, раздел 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 };
}

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

Ответ 4

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

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

Ответ 5

Ваш код

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).

Ответ 6

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