Type
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.
Contents | 
[edit] Type classification
The C++ type system consists of the following types:
- Fundamental types (see also std::is_fundamental)
 
- 
- The type void (see also std::is_void)
 - The type std::nullptr_t (see also std::is_null_pointer)
 - Arithmetic types (see also std::is_arithmetic)
 
- 
- Floating-point types (float, double, long double) (see also std::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)
 
 
- Signed integer types (short, int, long, long long)
 - Unsigned integer types (unsigned short, unsigned int, unsigned long, unsigned long long)
 
 
 
 
- Compound types (see also std::is_compound)
 
- 
- Reference (see also std::is_reference)
 
- 
- Lvalue reference (see also std::is_lvalue_reference)
 - Rvalue reference (see also std::is_rvalue_reference)
 
 
- Pointer (see also std::is_pointer)
 
- Pointer to member (see also std::is_member_pointer)
 
- Array (see also std::is_array)
 - Function (see also std::is_function)
 - Enumeration (see also std::is_enum)
 - Class types
 
- 
- Non-union class types (see also std::is_class)
 - Unions (see also std::is_union)
 
 
 
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 type: any type other than void, function, or reference (that is, a type that an object may have). (see also std::is_object)
 -  scalar type: arithmetic, pointer, enumeration, 
std::nullptr_t(see also std::is_scalar) - std::is_trivial, std::is_pod, std::is_literal_type, and other categories listed in the the type traits library or as named type requirements.
 
[edit] 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
 
| This section is incomplete Reason: 8.2[dcl.ambig.res] if it can be compactly summarized  | 
| This section is incomplete Reason: mention and link to decltype and auto  | 
[edit] 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.
| This section is incomplete Reason: 7.1.6.3[dcl.type.elab] + 3.4.4[basic.lookup.elab], probably worth splitting off into its own page, which may even pull most of 9.1[class.name]/2-3} out of cpp/language/class  | 
[edit] 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.
[edit] 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.
[edit] Incomplete type
The following types are incomplete types
- the type void
 - class type that has been declared (e.g. by forward declaration) but not defined
 - array of unknown size
 - 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 
Tor 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 
Tor 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.
| This section is incomplete Reason: rules for completing the incomplete types from §3.9[basic.types]/6  |