Почему класс {int i; }; не полностью соответствует стандартам?

Это дополнительный вопрос.

впредыдущий вопрос@ JohannesSchaub-litb сказал, что следующий кодне полностью соответствует стандартам:

class { int i; };  //unnamed-class definition. § 9/1 allows this!

а потом он добавил,

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

Я не мог этого понять. Какое имя он говорит?

Может ли кто-нибудь более подробно остановиться на этом (желательно со ссылкой на Стандарт)?

 jcoder30 окт. 2012 г., 14:29
Это эквивалентно написанию: "int;" как строка кода. Он называет тип, но не дает ему имя.
 Henning Makholm30 окт. 2012 г., 13:08
Какое имя он говорит? Один, которыйнет там, Объявление не объявляет имя класса, а также не объявляет имя typedef или переменную / функцию - ничего не добавляется в область, в которой объявление появляется в результате объявления.

Ответы на вопрос(5)

Сообщение об ошибке от GCC объясняет это довольно кратко:

$ cat > a.cc
class { int i; };
$ g++ -Wall -std=c++98 a.cc
a.cc:1: error: abstract declarator ‘<anonymous class>’ used as declaration

class { int i; } являетсяабстрактно-описатель (Стандарт, § 8), но не действительныйдекларация (§ 7). Это правило, на которое ссылается @ JohannesSchaub-litb: для правильного объявления вам нужно что-то объявить, например, имя класса или имя переменной.

class { int i; }; не является действительным объявлением, потому что этопростая декларация безINIT-описатель-лист но это не вводит (или повторно объявляет) имя класса.

ИСО / МЭК 14882: 2011 7 [dcl.dcl] / 3:

Впростая декларациянеобязательныйINIT-описатель-лист может быть опущено только при объявлении класса (раздел 9) или перечисления (7.2), то есть когдаДецл-спецификатор-сл содержит либокласса спецификатор,elaboratedtype спецификатор скласс-ключ (9.1) илиперечисление спецификатор, В этих случаях и всякий раз, когдакласса спецификатор или жеперечисление спецификатор присутствует вДецл-спецификатор-слидентификаторы в этих спецификаторах входят в число имен, объявляемых объявлением (какКласс-имена, перечисляемые-имена, или женумераторыв зависимости от синтаксиса).В таких случаях и за исключением объявления безымянного битового поля (9.6),Децл-спецификатор-сл должен ввести одно или несколько имен в программу или переименовать имя, введенное предыдущим объявлением.

class{ int i; }; вы собираете кучу символов (int iв этом случае) вы не сможете использовать где-либо еще в любом коде.

Чтобы этот код имел смысл, вы должны по крайней мере выполнить одно из следующих действий:

class Myclass { int i; }; //I can furthermore instantiate variables of Myclass
class { int i; } myvar; //This in fact creates a myvar object
typedef class { int i; } MyType; //I can funthermore instantiate variables of MyType

Говоря простоclass{ int i; }; вы говорите компилятору:

держатьint и назовите этоi,завернуть вclass Я никогда не позвоню и ...забудь это! (};)

Если вы удалите это объявление из вашей программы, ничего не изменится.

 interjay30 окт. 2012 г., 13:38
Очевидно, что объявление класса бесполезно, но это не отвечает на вопрос, разрешено ли оно. Есть много бесполезных конструкций, которые разрешены стандартом. Почему так много голосов?
 Griwes30 окт. 2012 г., 13:49
+1 за случайный грустный смайлик -}; : D
 Griwes30 окт. 2012 г., 14:45
@interjay, я голосовал за это. И написал "+1", как в "хорошем", а не "Я тебя голосую". Я различаю «+1» и «Upvote».
 Jon30 окт. 2012 г., 13:37
Это все хорошо, но ИМХО необходимо явно согласиться или не согласиться с «этот код не соответствует стандартам» в явном виде.
 interjay30 окт. 2012 г., 13:52
@Griwes: Может быть, вам следует голосовать на основе того, ответил ли он вместо этого на вопрос.
Решение Вопроса

class {public: int i;} (обратите внимание на отсутствие последней точки с запятой), потому что этоДецл-спецификатор-сл для безымянного класса может использоваться другая конструкция, такая как typedef или объявление переменной. Проблема сclass {public: int i;}; (обратите внимание, что последняя точка с запятой теперь присутствует) заключается в том, что эта спецификация класса теперь становится объявлением. Это незаконная декларация в соответствии с пунктом 7 пункта 3 стандарта:

В таких случаях и за исключением объявления безымянного битового поля (9.6),Децл-спецификатор-сл должен ввести одно или несколько имен в программу или переименовать имя, введенное предыдущим объявлением.

 Thomas Matthews30 окт. 2012 г., 17:11
+1 для уточнения междуДецл-спецификатор-сл идекларация.

[basic.scope.pdecl]/6, который говорит:

Точка объявления класса, впервые объявленного в подробном спецификаторе типа, следующая:
- для декларации формы
class-key attribute-specifier-seqopt identifier ;

идентификатор объявляется как имя класса в области, содержащей объявление, в противном случае
- для уточненного спецификатора типа формы
class-key identifier

если разработанный спецификатор типа используется в выражении decl-specier-seq или параметр-объявление функции, определенной в области пространства имен, идентификатор объявляется как имя класса в пространстве имен, которое содержит объявление; в противном случае, за исключением объявления друга, идентификатор объявляется в наименьшем пространстве имен или области блока, содержащей объявление. [Примечание: эти правила также применяются в шаблонах. - примечание конца] [Примечание: другие формы разработанного спецификатора типа не объявляют новое имя, и поэтому должны ссылаться на существующее имя типа. См. 3.4.4 и 7.1.6.3. - конец примечания]

вы не создаете переменную анонимного типавы не создаете тип

Есть еще один пример (в[basic.def]/2) из стандарта, подтверждающего, что ваш пример не соответствует стандарту:

struct S { int a; int b; };       // defines S, S::a, and S::b
struct X {                        // defines X
  int x;                          // defines non-static data member x
  static int y;                   // declares static data member y
  X(): x(0) { }                   // defines a constructor of X
};
int X::y = 1;                     // defines X::y
enum { up, down };                // defines up and down
namespace N { int d; }            // defines N and N::d
namespace N1 = N;                 // defines N1
X anX;                            // defines anX

Ваш пример не определяет ничего (кроме анонимной структуры, к которой нельзя получить доступ).

Обратите внимание на исключение в enum, потому что в этом случае вводятся два значения.

Ваш ответ на вопрос