Typedef and type aliases
Introduction#
The typedef
and (since C++11) using
keywords can be used to give a new name to an existing type.
Syntax#
- typedef type-specifier-seq init-declarator-list;
- attribute-specifier-seq typedef decl-specifier-seq init-declarator-list; // since C++11
- using identifier attribute-specifier-seq(opt) = type-id; // since C++11
Basic typedef syntax
A typedef
declaration has the same syntax as a variable or function declaration, but it contains the word typedef
. The presence of typedef
causes the declaration to declare a type instead of a variable or function.
int T; // T has type int
typedef int T; // T is an alias for int
int A[100]; // A has type "array of 100 ints"
typedef int A[100]; // A is an alias for the type "array of 100 ints"
Once a type alias has been defined, it can be used interchangeably with the original name of the type.
typedef int A[100];
// S is a struct containing an array of 100 ints
struct S {
A data;
};
typedef
never creates a distinct type. It only gives another way of referring to an existing type.
struct S {
int f(int);
};
typedef int I;
// ok: defines int S::f(int)
I S::f(I x) { return x; }
More complex uses of typedef
The rule that typedef
declarations have the same syntax as ordinary variable and function declarations can be used to read and write more complex declarations.
void (*f)(int); // f has type "pointer to function of int returning void"
typedef void (*f)(int); // f is an alias for "pointer to function of int returning void"
This is especially useful for constructs with confusing syntax, such as pointers to non-static members.
void (Foo::*pmf)(int); // pmf has type "pointer to member function of Foo taking int
// and returning void"
typedef void (Foo::*pmf)(int); // pmf is an alias for "pointer to member function of Foo
// taking int and returning void"
It is hard to remember the syntax of the following function declarations, even for experienced programmers:
void (Foo::*Foo::f(const char*))(int);
int (&g())[100];
typedef
can be used to make them easier to read and write:
typedef void (Foo::pmf)(int); // pmf is a pointer to member function type
pmf Foo::f(const char*); // f is a member function of Foo
typedef int (&ra)[100]; // ra means "reference to array of 100 ints"
ra g(); // g returns reference to array of 100 ints
Declaring multiple types with typedef
The typedef
keyword is a specifier, so it applies separately to each declarator. Therefore, each name declared refers to the type that that name would have in the absence of typedef
.
int *x, (*p)(); // x has type int*, and p has type int(*)()
typedef int *x, (*p)(); // x is an alias for int*, while p is an alias for int(*)()
Alias declaration with “using”
The syntax of using
is very simple: the name to be defined goes on the left hand side, and the definition goes on the right hand side. No need to scan to see where the name is.
using I = int;
using A = int[100]; // array of 100 ints
using FP = void(*)(int); // pointer to function of int returning void
using MP = void (Foo::*)(int); // pointer to member function of Foo of int returning void
Creating a type alias with using
has exactly the same effect as creating a type alias with typedef
. It is simply an alternative syntax for accomplishing the same thing.
Unlike typedef
, using
can be templated. A “template typedef” created with using
is called an alias template.