Type

From cppreference.com
< cpp‎ | language

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:

  • 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)

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:

[edit] Type naming

A name can be declared to refer to a type by means of

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:

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

[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.

[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:

(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.