В нижеприведенном фрагменте я могу понять (из пункта 3.3.2/6 second bullet point), что имя B
в объявлении struct B* p;
вводится в глобальное пространство имен как имя класса.Является ли моя интерпретация слова «первая» в п. 3.3.2/6 правильной?
struct A {
// struct B{};
int B;
struct B* p;
};
void f(B&) {}
int main()
{
A a;
f(*a.p);
}
§3.3.2/6:
Точка декларации класса первого объявленного в разработаны типа спецификатор выглядит следующим образом:
за декларацию
ключ классаатрибут-спецификатор-0optидентификатор;
идентификатор объявляется класс имяв объеме, что содержит объявление, в противном случае
для разработан типа-спецификатор формы
ключ классаидентификатор
если выработанного типа спецификатор используются в Decl-спецификаторе-след или параметра-декларация-п функции, определенной в области видимости пространства имен, то идентификатор объявлен как класс имя- в в пространстве имен, содержащем объявление; в противном случае, кроме объявления , идентификатор - это , объявленный в наименьшем пространстве имен или блоке, который содержит объявление . [Примечание: Эти правила также применяются в шаблонах. - конец примечания] [Примечания: Другие формы разработаны типа-спецификатор не объявить новое имя, и, следовательно, должны относиться к существующему имени-типа. См. 3.4.4 и 7.1.6.3. - конец примечание]
Однако если раскомментировать определение struct B{};
внутри struct A
, что я сказал ранее в отношении введения имени B
в глобальное пространство имен, не происходит больше, поскольку код не компилируется.Я считаю, что это имеет не делать со словом первый (курсив мой) выше, так как теперь имя класса B
, в декларации struct B* p;
больше не его первая декларация в декларативной области. Правильно ли я это сказал?
Предполагая, что моя интерпретация верна, почему это класс-имяB
не вводится в глобальное пространство имен в этом случае? Обратите внимание, что вложенный класс struct B{};
будет скрыт внутри A в этом случае, то есть даже если мы изменим объявление функции f
на void f(A::B&)
, код не будет компилироваться.
Есть еще один момент, который мне не ясен: что заставило разработчиков принять решение о введении имени класса в пространство имен или о блокировке области, содержащей спецификатор специфицированного типа, во второй пуле пункт выше? То есть, почему они не оставили декларацию имени класса внутри класса?
Впрыск в охватывающее пространство имен, безусловно, совместим с C. – avakar
Не могли бы вы изучить это немного больше? –
C не имеет области класса/структуры, поэтому 'struct S {struct X {int y; }; int x; }; struct X my_var = {42}; 'является законным в C (ну, это уродливо - но он фактически компилируется с clang и gcc, хотя и с предупреждением в последнем). – dyp