10 Declarations [dcl.dcl]

10.1 Specifiers [dcl.spec]

10.1.3 The typedef specifier [dcl.typedef]

Объявления, содержащие 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 noteExample:

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]