Elaborated type specifier
Уточненные спецификаторы типа могут использоваться для обращения к ранее объявленному имени класса (class, struct или union) или к ранее объявленному имени перечисления, даже если имя было скрыто объявлением не-типа . Они также могут использоваться для объявления новых имен классов.
Содержание |
Синтаксис
| class-key class-name | (1) | ||||||||
enum
enum-name
|
(2) | ||||||||
class-key
attr
(необязательно)
identifier
;
|
(3) | ||||||||
| class-key | - | один из class , struct , union |
| class-name | - | имя ранее объявленного типа класса, опционально квалифицированное , или идентификатор, ранее не объявленный как имя типа |
| enum-name | - | имя ранее объявленного типа перечисления, опционально квалифицированное |
| attr | - | (начиная с C++11) любое количество атрибутов |
Объявление непрозрачного перечисления напоминает форму (3) , но тип перечисления становится полным типом после объявления непрозрачного перечисления.
Объяснение
Форма (3) является частным случаем elaborated type specifier, обычно называемым forward declaration классов. Для описания формы (3) см. Forward declaration . Следующее относится только к форме (1) и (2) .
class-name или enum-name в уточненном спецификаторе типа может быть либо простым идентификатором, либо qualified-id . Поиск имени выполняется с использованием unqualified name lookup или qualified name lookup , в зависимости от их формы. Однако в обоих случаях имена не-типов не рассматриваются.
class T { public: class U; private: int U; }; int main() { int T; // ошибка: найдена локальная переменная T class T t; // OK: находит ::T, локальная переменная T игнорируется T::U* u; // ошибка: поиск T::U находит приватный член данных class T::U* u; // OK: член данных игнорируется }
Если поиск имени не находит ранее объявленное имя типа, а уточненный-спецификатор-типа вводится с помощью
class
,
struct
, или
union
(т.е. не с помощью
enum
), и
class-name
является неквалифицированным идентификатором, тогда уточненный-спецификатор-типа является объявлением класса с именем class-name, и целевой областью видимости является ближайшая охватывающая пространство имен или блочная область видимости.
template<typename T> struct Node { struct Node* Next; // OK: поиск Node находит injected-class-name struct Data* Data; // OK: объявляет тип Data в глобальной области видимости // и также объявляет член данных Data friend class ::List; // ошибка: нельзя вводить квалифицированное имя enum Kind* kind; // ошибка: нельзя вводить перечисление }; Data* p; // OK: структура Data была объявлена
Если имя ссылается на typedef-имя , псевдоним типа , параметр шаблона типа или специализацию шаблона псевдонима , программа является некорректной, в противном случае уточненный спецификатор типа вводит имя в объявление таким же образом, как простой спецификатор типа вводит свое имя-типа.
template<typename T> class Node { friend class T; // ошибка: параметр типа не может использоваться в уточненном спецификаторе типа; // примечание: аналогичное объявление `friend T;` допустимо. }; class A {}; enum b { f, t }; int main() { class A a; // OK: эквивалентно 'A a;' enum b flag; // OK: эквивалентно 'b flag;' }
class-key
или ключевое слово
enum
в уточненном спецификаторе типа должны соответствовать по типу объявлению, на которое ссылается имя в уточненном спецификаторе типа.
-
ключевое слово
enumдолжно использоваться для обращения к типу перечисления (будь то область видимости или без области видимости) -
ключевое слово
unionclass-key должно использоваться для обращения к объединению -
либо ключевое слово
classилиstructclass-key должно использоваться для обращения к типу класса, не являющемуся объединением (ключевые словаclassиstructздесь взаимозаменяемы).
enum class E { a, b }; enum E x = E::a; // OK enum class E y = E::b; // ошибка: 'enum class' не может использоваться в уточненном спецификаторе типа struct A {}; class A a; // OK
При использовании в качестве
аргумента шаблона
,
class
T
является параметром шаблона типа с именем
T
, а не безымянным параметром-константой, тип
T
которого вводится спецификатором elaborated type.
Ключевые слова
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 6.5.6 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 9.2.9.4 Уточненные спецификаторы типа [dcl.type.elab]
- Стандарт C++20 (ISO/IEC 14882:2020):
-
- 6.5.4 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 9.2.8.3 Уточненные спецификаторы типа [dcl.type.elab]
- Стандарт C++17 (ISO/IEC 14882:2017):
-
- 6.4.4 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 10.1.7.3 Уточненные спецификаторы типа [dcl.type.elab]
- Стандарт C++14 (ISO/IEC 14882:2014):
-
- 3.4.4 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 7.1.6.3 Уточненные спецификаторы типа [dcl.type.elab]
- Стандарт C++11 (ISO/IEC 14882:2011):
-
- 3.4.4 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 7.1.6.3 Уточненные спецификаторы типа [dcl.type.elab]
- Стандарт C++98 (ISO/IEC 14882:1998):
-
- 3.4.4 Уточненные спецификаторы типа [basic.lookup.elab]
-
- 7.1.5.3 Уточненные спецификаторы типа [dcl.type.elab]
|
Этот раздел не завершён
Причина: вероятно следует перенести большую часть 9.1[class.name]/2-3 из cpp/language/class |