Objects, references, functions including function template specializations, and expressions have a property called type, which both restricts the operations that are permitted for those entities and provides semantic meaning to the otherwise generic sequences of bits.
Type classification
The C++ type system consists of the following types:
- fundamental types (see also
std::is_fundamental
): - the type
void
(see alsostd::is_void
); - the type
std::nullptr_t
(see alsostd::is_null_pointer
); - arithmetic types (see also
std::is_arithmetic
): - floating-point types (
float
,double
,long double
) (see alsostd::is_floating_point
); - integral types (see also
std::is_integral
): - the type
bool
; - character types:
- narrow character types (
char
,signed char
,unsigned char
); - wide character types (
char16_t
,char32_t
,wchar_t
);
- narrow character types (
- signed integer types (
short int
,int
,long int
,long long int
); - unsigned integer types (
unsigned short int
,unsigned int
,unsigned long int
,unsigned long long int
); - compound types (see also
std::is_compound
): - reference types (see also
std::is_reference
): - lvalue reference types (see also
std::is_lvalue_reference
):- lvalue reference to object types;
- lvalue reference to function types;
- rvalue reference types (see also
std::is_rvalue_reference
):- rvalue reference to object types;
- rvalue reference to function types;
- pointer types (see also
std::is_pointer
):- pointer to object types;
- pointer to function types;
- pointer to member types (see also
std::is_member_pointer
):- pointer to member object types (see also
std::is_member_object_pointer
); - pointer to member function types (see also
std::is_member_function_pointer
);
- pointer to member object types (see also
- array types (see also
std::is_array
); - function types (see also
std::is_function
); - enumeration types (see also
std::is_enum
); - class types:
- non-union types (see also
std::is_class
); - union types (see also
std::is_union
).
- non-union types (see also
For every type other than reference and function, the type system supports three additional cv-qualified versions of that type (const
, volatile
, and const volatile
).
Types are grouped in various categories based on their properties:
- object types: any type other than cv void, function, or reference (that is, a type that an object may have) (see also
std::is_object
); - scalar types: arithmetic, pointer, enumeration,
std::nullptr_t
(see alsostd::is_scalar
); - trivial types (see also
std::is_trivial
), POD types (see alsostd::is_pod
), literal types (see alsostd::is_literal_type
), and other categories listed in the the type traits library or as named type requirements.
Type naming
A name can be declared to refer to a type by means of:
- class declaration;
- enum declaration;
- typedef declaration;
- type alias declaration.
Types that do not have names often need to be referred to in C++ programs; the syntax for that is known as type-id. The syntax of the type-id that names type T is exactly the syntax of a declaration of a variable or function of type T, with the identifier omitted, except that decl-specifier-seq of the declaration grammar is constrained to type-specifier-seq. New types may be declared.
int* p; // declration of a pointer to int static_cast<int*>(p); // type-id is "int*" int a[3]; // declaration of an array of 3 int new int[3]; // type-id is "int[3]" int (*(*x[2])())[3]; // declaration of an array of 2 pointers to functions // returning pointer to array of 3 int new (int (*(*[2])())[3]); // type-id is "int (*(*[2])())[3]" void f(int); // declaration of a function that takes int and returns void std::function<void(int)> x = f; // type template parameter is a type-id "void(int)" std::vector<int> v; // declaration of a vector of int sizeof(std::vector<int>); // type-id is "std::vector<int>" struct { int x; } b; // creates a new type and declares an object b of that type sizeof(struct{ int x; }); // error: cannot define new types in a sizeof expression using t = struct { int x; }; // creates a new type and declares t as an alias of that type sizeof(static int); // error: storage class specifiers not part of type-specifier-seq std::function<inline void(int)> f; // error: function specifiers aren't either
The declarator part of the declaration grammar with the name removed is referred to as abstract-declarator.
Type-id may be used in the following situations:
- to specify the target type in cast expressions;
- as arguments to sizeof, alignof, alignas, new, and typeid;
- on the right hand side of an type alias declaration;
- as the trailing return type of a function declaration;
- as the default argument of a template type parameter;
- as the template argument for a template type parameter;
- in dynamic exception specification.
Type-id can be used with some modifications in the following situations:
- in the parameter list of a function (when the parameter name is omitted), type-id uses decl-specifier-seq instead of type-specifier-seq (in particular, some storage class specifiers are allowed);
- in the name of a user-defined conversion function, the abstract declarator cannot include function or array operators.
Elaborated type specifier
Elaborated type specifiers may be used to refer to a previously-declared class name (class, struct, or union) or to a previously-declared enum name even if the name was hidden by a non-type declaration. They may also be used to declare new class names.
See elaborated type specifier for details.
Static type
The type of an expression that results from the compile-time analysis of the program is known as the static type of the expression. The static type does not change while the program is executing.
Dynamic type
If some glvalue expression refers to a polymorphic object, the type of its most derived object is known as the dynamic type.
// given struct B { virtual ~B() {} }; // polymorphic type struct D: B {}; // polymorphic type D d; // most-derived object B* ptr = &d; // the static type of (*ptr) is B // the dynamic type of (*ptr) is D
For prvalue expressions, the dynamic type is always the same as the static type.
Incomplete type
The following types are incomplete types:
- the type
void
(possibly cv-qualified); - class type that has been declared (e.g. by forward declaration) but not defined;
- array of unknown bound;
- array of elements of incomplete type;
- enumeration type from the point of declaration until its underlying type is determined.
Any of the following contexts requires class T
to be complete:
- definition or function call to a function with return type
T
or argument typeT
; - definition of an object of type
T
; - declaration of a non-static class data member of type
T
; - new-expression for an object of type
T
or an array whose element type isT
; - lvalue-to-rvalue conversion applied to a glvalue of type
T
; - an implicit or explicit conversion to type
T
; - a standard conversion, dynamic_cast, or static_cast to type
T*
orT&
, except when converting from the null pointer constant or from a pointer to void; - class member access operator applied to an expression of type
T
; - typeid, sizeof, or alignof operator applied to type
T
; - arithmetic operator applied to a pointer to
T
; - definition of a class with base class
T
; - assignment to an lvalue of type
T
; - a catch-clause for an exception of type
T
,T&
, orT*
.
(In general, when the size and layout of T
must be known.).
If any of these situations occur in a translation unit, the definition of the type must appear in the same translation unit. Otherwise, it is not required.
See also
C documentation for Type |
Please login to continue.