Почему С++ запрещает анонимные структуры?
Некоторые компиляторы С++ разрешают анонимные объединения и структуры как расширение стандартного С++. Это немного синтаксического сахара, который иногда очень полезен.
Какое обоснование мешает этому быть частью стандарта? Есть ли технологический блокпост? Философский? Или просто недостаточно для его оправдания?
Вот пример того, что я говорю:
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: Анонимные структуры, я буду опасаться - это плохо подходит для концепция инкапсуляции. Я бы не ожидал, что член класса будет путаться с моим пространством имен классов за пределами простого добавления одного члена. Кроме того, изменения анонимной структуры могут повлиять на мой класс без разрешения.