Объявления, содержащие decl-specifier typedef идентификаторы объявления, которые можно использовать позже для именования fundamental или compound типов. Спецификатор typedef не должен сочетаться в a decl-specifier-seqс любым другим типом спецификатора, кроме a defining-type-specifier, и он не должен использоваться ни в decl-specifier-seqa, parameter-declarationни в decl-specifier-seqa function-definition([dcl.fct.def]). Если typedef спецификатор появляется в объявлении без символа declarator, программа имеет неправильный формат.
typedef-name: identifier
Имя, объявленное с помощью typedef спецификатора, становится typedef-name. В рамках своего объявления a typedef-nameсинтаксически эквивалентен ключевому слову и называет тип, связанный с идентификатором, способом, описанным в пункте [dcl.decl]. Таким образом, А является синонимом другого типа. A не вводит новый тип, как это делает объявление класса ( ) или объявление перечисления. [ Послеtypedef-nametypedef-name[class.name] Example:
typedef int MILES, *KLICKSP;
конструкции
MILES distance; extern KLICKSP metricp;
все правильные объявления; тип distance is int и тип metricp is «указатель на int». ] — end example
A typedef-nameтакже может быть введено через alias-declaration. identifierВслед за using ключевым словом становится typedef-name и опциональным attribute-specifier-seqследуя identifierвходит в этот typedef-name. Такой объект typedef-nameимеет такую же семантику, как если бы он был введен typedef спецификатором. В частности, он не определяет новый тип. [ Example:
using handler_t = void (*)(int); extern handler_t ignore; extern void (*ignore)(int); // redeclare ignore using cell = pair<void*, cell*>; // ill-formed
— end example ] defining-type-specifier-seq Из defining-type-idне определяет класс или перечисление , если alias-declaration это declarationиз template-declaration.
В данной области, не относящейся к классу, typedef спецификатор может использоваться для переопределения имени любого типа, объявленного в этой области, для ссылки на тип, на который он уже ссылается. [ Example:
typedef struct s { /* ... */ } s;
typedef int I;
typedef int I;
typedef I I;
— end example ]
В заданной области действия класса typedef спецификатор может использоваться для переопределения любого class-nameобъявленного в этой области действия, который не является также typedef-nameссылкой на тип, на который он уже ссылается. [ Example:
struct S { typedef struct A { } A; // OK typedef struct B B; // OK typedef A A; // error };
— end example ]
Если typedef спецификатор используется для переопределения в данной области сущности, на которую можно ссылаться с помощью elaborated-type-specifier, на эту сущность можно продолжать ссылаться с помощью elaborated-type-specifierили как перечисление или имя класса в перечислении или определении класса соответственно. [ Example:
struct S; typedef struct S S; int main() { struct S* p; // OK } struct S { }; // OK
— end example ]
В данной области typedef спецификатор не должен использоваться для переопределения имени любого типа, объявленного в этой области, для ссылки на другой тип. [ Example:
class complex { /* ... */ }; typedef int complex; // error: redefinition
— end example ]
Точно так же в данной области действия класс или перечисление не должны объявляться с тем же именем, что и объект typedef-name, объявленный в этой области, и относится к типу, отличному от самого класса или перечисления. [ Example:
typedef int complex; class complex { /* ... */ }; // error: redefinition
— end example ]
[ Имя типа класса или его cv-квалифицированная версия также является ( ). Если a используется для идентификации объекта , определения, объявления или объявления, программа имеет неправильный формат . ] [ Note: typedef-nameclass-name[class.name]typedef-nameelaborated-type-specifier class constructor destructor — end note Example:
struct S { S(); ~S(); }; typedef struct S T; S a = T(); // OK struct T * p; // error
— end example ]
Если объявление typedef определяет безымянный класс (или перечисление), первый typedef-nameобъявленный в объявлении тип этого класса (или тип перечисления) используется для обозначения типа класса (или типа перечисления) только для целей связывания ([basic.link]). [ Example:
typedef struct { } *ps, S; // S is the class name for linkage purposes
— end example ]