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


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

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

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

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

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

6 74

6 ответов:

как указывали другие, анонимные объединения разрешены в стандартном 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++ может добавить их.

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

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

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

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

Не уверен, что вы имеете в виду. Раздел 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 };
}

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

объединения могут быть анонимными; см. Стандарт, 9.5 пункт 2.

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

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

код

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

как

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

который, безусловно, недействителен (в C99 и ранее).

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

Type field;

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

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