[basic.types]

# 6 Basics [[basic]](./#basic)

## 6.9 Types [basic.types]

### [6.9.1](#general) General [[basic.types.general]](basic.types.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5030)

[*Note [1](#general-note-1)*:

[basic.types] and the subclauses thereof
impose requirements on implementations regarding the representation
of types[.](#general-1.sentence-1)

There are two kinds of types: fundamental types and compound types[.](#general-1.sentence-2)

Types describe [objects](intro.object "6.8.2 Object model [intro.object]"),[references](dcl.ref "9.3.4.3 References [dcl.ref]"),
or [functions](dcl.fct "9.3.4.6 Functions [dcl.fct]")[.](#general-1.sentence-3)

â *end note*]

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5041)

For any object (other than a potentially-overlapping subobject) of trivially copyable typeT, whether or not the object holds a valid value of typeT, the underlying bytes ([[intro.memory]](intro.memory "6.8.1 Memory model")) making up the
object can be copied into an array ofchar,unsigned char, orstd​::​byte ([[cstddef.syn]](cstddef.syn "17.2.1 Header <cstddef> synopsis"))[.](#general-2.sentence-1)[26](#footnote-26 "By using, for example, the library functions ([headers]) std​::​memcpy or std​::​memmove.")

If the content of that array
is copied back into the object, the object shall
subsequently hold its original value[.](#general-2.sentence-2)

[*Example [1](#general-example-1)*: constexpr std::size_t N = sizeof(T);char buf[N];
T obj; // obj initialized to its original value std::memcpy(buf, &obj, N); // between these two calls to std​::​memcpy, obj might be modified std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type holds its original value â *end example*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5068)

For two distinct objects obj1 and obj2 of trivially copyable type T,
where neither obj1 nor obj2 is a potentially-overlapping subobject,
if the underlying bytes ([[intro.memory]](intro.memory "6.8.1 Memory model")) making upobj1 are copied into obj2,[27](#footnote-27 "By using, for example, the library functions ([headers]) std​::​memcpy or std​::​memmove.")obj2 shall subsequently hold the same value asobj1[.](#general-3.sentence-1)

[*Example [2](#general-example-2)*: T* t1p;
T* t2p; // provided that t2p points to an initialized object ... std::memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of trivially copyable type in *t1p contains// the same value as the corresponding subobject in *t2p â *end example*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5092)

The [*object representation*](#def:representation,object "6.9.1 General [basic.types.general]") of a complete object type T is the
sequence of *N* unsigned char objects taken up
by a non-bit-field complete object of type T,
where *N* equalssizeof(T)[.](#general-4.sentence-1)

The [*value representation*](#def:representation,value "6.9.1 General [basic.types.general]") of a type T is the set of bits
in the object representation of T that participate in representing a value of type T[.](#general-4.sentence-2)

The object and value representation of
a non-bit-field complete object of type T are
the bytes and bits, respectively, of
the object corresponding to the object and value representation of its type[.](#general-4.sentence-3)

The object representation of a bit-field object is
the sequence of *N* bits taken up by the object,
where *N* is the width of the bit-field ([[class.bit]](class.bit "11.4.10 Bit-fields"))[.](#general-4.sentence-4)

The value representation of a bit-field object is
the set of bits in the object representation that
participate in representing its value[.](#general-4.sentence-5)

Bits in the object representation of a type or object that are
not part of the value representation
are [*padding bits*](#def:padding_bits "6.9.1 General [basic.types.general]")[.](#general-4.sentence-6)

For trivially copyable types, the value representation is
a set of bits in the object representation that determines a[*value*](#def:value "6.9.1 General [basic.types.general]"), which is one discrete element of animplementation-defined set of values[.](#general-4.sentence-7)[28](#footnote-28 "The intent is that the memory model of C++ is compatible with that of the C programming language.")

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5127)

A class that has been declared but not defined, an enumeration type in certain
contexts ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), or an array of unknown
bound or of incomplete element type, is an[*incompletely-defined object type*](#def:object_type,incompletely-defined "6.9.1 General [basic.types.general]")[.](#general-5.sentence-1)[29](#footnote-29 "The size and layout of an instance of an incompletely-defined object type is unknown.")

Incompletely-defined object types and cv void are[*incomplete types*](#def:type,incomplete "6.9.1 General [basic.types.general]") ([[basic.fundamental]](#basic.fundamental "6.9.2 Fundamental types"))[.](#general-5.sentence-2)

[*Note [2](#general-note-2)*:

Objects cannot be defined to have an incomplete type ([[basic.def]](basic.def "6.2 Declarations and definitions"))[.](#general-5.sentence-3)

â *end note*]

[6](#general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5144)

A class type (such as âclass Xâ) can be incomplete at one
point in a translation unit and complete later on; the type
âclass Xâ is the same type at both points[.](#general-6.sentence-1)

The declared type
of an array object can be an array of incomplete class type and
therefore incomplete; if the class type is completed later on in the
translation unit, the array type becomes complete; the array type at
those two points is the same type[.](#general-6.sentence-2)

The declared type of an array object
can be an array of unknown bound and therefore be incomplete at one
point in a translation unit and complete later on; the array types at
those two points (âarray of unknown bound of Tâ and âarray ofN Tâ) are different types[.](#general-6.sentence-3)

[*Note [3](#general-note-3)*:

The type of a pointer or reference to array of unknown bound
permanently points to or refers to an incomplete type[.](#general-6.sentence-4)

An array of unknown bound named by a typedef declaration
permanently refers to an incomplete type[.](#general-6.sentence-5)

In either case, the array type cannot be completed[.](#general-6.sentence-6)

â *end note*]

[*Example [3](#general-example-3)*:

[ð](#:type,example_of_incomplete)

class X; // X is an incomplete typeextern X* xp; // xp is a pointer to an incomplete typeextern int arr[]; // the type of arr is incompletetypedef int UNKA[]; // UNKA is an incomplete type UNKA* arrp; // arrp is a pointer to an incomplete type UNKA** arrpp;

void foo() { xp++; // error: X is incomplete arrp++; // error: incomplete type arrpp++; // OK, sizeof UNKA* is known}struct X { int i; }; // now X is a complete typeint arr[10]; // now the type of arr is complete X x;void bar() { xp = &x; // OK; type is âpointer to X'' arrp = &arr; // OK; qualification conversion ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) xp++; // OK, X is complete arrp++; // error: UNKA can't be completed} â *end example*]

[7](#general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5192)

[*Note [4](#general-note-4)*:

The rules for declarations and expressions describe in which
contexts incomplete types are prohibited[.](#general-7.sentence-1)

â *end note*]

[8](#general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5198)

An [*object type*](#def:object_type "6.9.1 General [basic.types.general]") is a (possibly cv-qualified) type that is not
a function type, not a reference type, and not cv void[.](#general-8.sentence-1)

[9](#general-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5203)

Arithmetic types ([[basic.fundamental]](#basic.fundamental "6.9.2 Fundamental types")), enumeration types,
pointer types, pointer-to-member types ([[basic.compound]](#basic.compound "6.9.4 Compound types")),std​::​meta​::​​info, std​::​nullptr_t,
and[cv-qualified](#basic.type.qualifier "6.9.5 CV-qualifiers [basic.type.qualifier]") versions of these
types are collectively called[*scalar types*](#def:type,scalar "6.9.1 General [basic.types.general]")[.](#general-9.sentence-1)

Scalar types, trivially copyable class types ([[class.prop]](class.prop "11.2 Properties of classes")),
arrays of such types, and cv-qualified versions of these
types are collectively called [*trivially copyable types*](#def:type,trivially_copyable "6.9.1 General [basic.types.general]")[.](#general-9.sentence-2)

Scalar types, trivially relocatable class types ([[class.prop]](class.prop "11.2 Properties of classes")),
arrays of such types, and cv-qualified versions of these
types are collectively called [*trivially relocatable types*](#def:type,trivially_relocatable "6.9.1 General [basic.types.general]")[.](#general-9.sentence-3)

Cv-unqualified scalar types, replaceable class types ([[class.prop]](class.prop "11.2 Properties of classes")), and
arrays of such types are collectively called[*replaceable types*](#def:type,replaceable "6.9.1 General [basic.types.general]")[.](#general-9.sentence-4)

Scalar types, standard-layout class
types ([[class.prop]](class.prop "11.2 Properties of classes")), arrays of such types, and
cv-qualified versions of these types
are collectively called [*standard-layout types*](#def:type,standard-layout "6.9.1 General [basic.types.general]")[.](#general-9.sentence-5)

Scalar types, implicit-lifetime class types ([[class.prop]](class.prop "11.2 Properties of classes")),
array types, and cv-qualified versions of these types
are collectively called [*implicit-lifetime types*](#def:type,implicit-lifetime "6.9.1 General [basic.types.general]")[.](#general-9.sentence-6)

[10](#general-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5238)

A type is a [*literal type*](#def:type,literal "6.9.1 General [basic.types.general]") if it is:

- [(10.1)](#general-10.1)

cv void; or

- [(10.2)](#general-10.2)

a scalar type; or

- [(10.3)](#general-10.3)

a reference type; or

- [(10.4)](#general-10.4)

an array of literal type; or

- [(10.5)](#general-10.5)

a possibly cv-qualified [class type](class "11 Classes [class]") that
has all of the following properties:
  * [(10.5.1)](#general-10.5.1)

it has a constexpr destructor ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers")),

  * [(10.5.2)](#general-10.5.2)

all of its non-variant non-static data members and base classes are of non-volatile literal types, and

  * [(10.5.3)](#general-10.5.3)

it
    +
          [(10.5.3.1)](#general-10.5.3.1)
is a closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")),

    +
          [(10.5.3.2)](#general-10.5.3.2)
is an aggregate union type that has either
no variant members or
at least one variant member of non-volatile literal type,

    +
          [(10.5.3.3)](#general-10.5.3.3)
is a non-union aggregate type for which
each of its anonymous union members
satisfies the above requirements for an aggregate union type, or

    +
          [(10.5.3.4)](#general-10.5.3.4)
has at least one constexpr constructor or constructor template
(possibly inherited ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")) from a base class)
that is not a copy or move constructor[.](#general-10.sentence-1)

[*Note [5](#general-note-5)*:

A literal type is one for which
it might be possible to create an object
within a constant expression[.](#general-10.sentence-2)

It is not a guarantee that it is possible to create such an object,
nor is it a guarantee that any object of that type
will be usable in a constant expression[.](#general-10.sentence-3)

â *end note*]

[11](#general-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5275)

Two types *cv1* T1 and *cv2* T2 are[*layout-compatible types*](#def:type,layout-compatible "6.9.1 General [basic.types.general]") if T1 and T2 are the same type,[layout-compatible enumerations](dcl.enum#def:layout-compatible,enumeration "9.8.1 Enumeration declarations [dcl.enum]"), or[layout-compatible standard-layout class types](class.mem#def:layout-compatible,class "11.4 Class members [class.mem]")[.](#general-11.sentence-1)

[12](#general-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5283)

A type is [*consteval-only*](#def:consteval-only "6.9.1 General [basic.types.general]") if it is eitherstd​::​meta​::​info or
a type compounded from a consteval-only type ([[basic.compound]](#basic.compound "6.9.4 Compound types"))[.](#general-12.sentence-1)

Every object of consteval-only type shall be

- [(12.1)](#general-12.1)

the object associated with a constexpr variable or a subobject thereof,

- [(12.2)](#general-12.2)

a template parameter object ([[temp.param]](temp.param "13.2 Template parameters")) or a subobject thereof, or

- [(12.3)](#general-12.3)

an object whose lifetime begins and ends
during the evaluation of a core constant expression[.](#general-12.sentence-2)

[26)](#footnote-26)[26)](#footnoteref-26)

By using, for example, the library
functions ([[headers]](headers "16.4.2.3 Headers")) std​::​memcpy or std​::​memmove[.](#footnote-26.sentence-1)

[27)](#footnote-27)[27)](#footnoteref-27)

By using, for example,
the library functions ([[headers]](headers "16.4.2.3 Headers")) std​::​memcpy or std​::​memmove[.](#footnote-27.sentence-1)

[28)](#footnote-28)[28)](#footnoteref-28)

The intent is that the memory model of C++ is compatible
with that of the C programming language[.](#footnote-28.sentence-1)

[29)](#footnote-29)[29)](#footnoteref-29)

The size and layout of an instance of an incompletely-defined
object type is unknown[.](#footnote-29.sentence-1)

### [6.9.2](#basic.fundamental) Fundamental types [[basic.fundamental]](basic.fundamental)

[1](#basic.fundamental-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5300)

There are five [*standard signed integer types*](#def:type,standard_signed_integer "6.9.2 Fundamental types [basic.fundamental]"):âsigned charâ, âshort intâ, âintâ,
âlong intâ, and âlong long intâ[.](#basic.fundamental-1.sentence-1)

In
this list, each type provides at least as much storage as those
preceding it in the list[.](#basic.fundamental-1.sentence-2)

There may also be implementation-defined[*extended signed integer types*](#def:type,extended_signed_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-1.sentence-3)

The standard and extended signed integer types are collectively called[*signed integer types*](#def:type,signed_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-1.sentence-4)

The range of representable values for a signed integer type isâ2Nâ1 to 2Nâ1â1 (inclusive),
where N is called the [*width*](simd.general#def:width "29.10.1 General [simd.general]") of the type[.](#basic.fundamental-1.sentence-5)

[*Note [1](#basic.fundamental-note-1)*:

Plain ints are intended to have
the natural width suggested by the architecture of the execution environment;
the other signed integer types are provided to meet special needs[.](#basic.fundamental-1.sentence-6)

â *end note*]

[2](#basic.fundamental-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5326)

For each of the standard signed integer types,
there exists a corresponding (but different)[*standard unsigned integer type*](#def:type,standard_unsigned_integer "6.9.2 Fundamental types [basic.fundamental]"):âunsigned charâ, âunsigned short intâ,
âunsigned intâ, âunsigned long intâ, and
âunsigned long long intâ[.](#basic.fundamental-2.sentence-1)

Likewise, for each of the extended signed integer types,
there exists a corresponding [*extended unsigned integer type*](#def:type,extended_unsigned_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-2.sentence-2)

The standard and extended unsigned integer types
are collectively called [*unsigned integer types*](#def:type,unsigned_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-2.sentence-3)

An unsigned integer type has the same width *N* as the corresponding signed integer type[.](#basic.fundamental-2.sentence-4)

The range of representable values for the unsigned type is0 to 2Nâ1 (inclusive);
arithmetic for the unsigned type is performed modulo 2N[.](#basic.fundamental-2.sentence-5)

[*Note [2](#basic.fundamental-note-2)*:

Unsigned arithmetic does not overflow[.](#basic.fundamental-2.sentence-6)

Overflow for signed arithmetic yields undefined behavior ([[expr.pre]](expr.pre "7.1 Preamble"))[.](#basic.fundamental-2.sentence-7)

â *end note*]

[3](#basic.fundamental-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5354)

An unsigned integer type has the same
object representation,
value representation, and
alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment"))
as the corresponding signed integer type[.](#basic.fundamental-3.sentence-1)

For each value x of a signed integer type,
the value of the corresponding unsigned integer type
congruent to x modulo 2N has the same value
of corresponding bits in its value representation[.](#basic.fundamental-3.sentence-2)[30](#footnote-30 "This is also known as two's complement representation.")

[*Example [1](#basic.fundamental-example-1)*:

The value â1 of a signed integer type has the same representation as
the largest value of the corresponding unsigned type[.](#basic.fundamental-3.sentence-3)

â *end example*]

Table [14](#tab:basic.fundamental.width) — Minimum width [[tab:basic.fundamental.width]](./tab:basic.fundamental.width)  

| [ð](#tab:basic.fundamental.width-row-1)<br>**Type** | **Minimum width N** |
| --- | --- |
| [ð](#tab:basic.fundamental.width-row-2)<br>signed char | 8 |
| [ð](#tab:basic.fundamental.width-row-3)<br>short int | 16 |
| [ð](#tab:basic.fundamental.width-row-4)<br>int | 16 |
| [ð](#tab:basic.fundamental.width-row-5)<br>long int | 32 |
| [ð](#tab:basic.fundamental.width-row-6)<br>long long int | 64 |

[4](#basic.fundamental-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5385)

The width of each standard signed integer type
shall not be less than the values specified in Table [14](#tab:basic.fundamental.width "Table 14: Minimum width")[.](#basic.fundamental-4.sentence-1)

The value representation of a signed or unsigned integer type
comprises N bits, where N is the respective width[.](#basic.fundamental-4.sentence-2)

Each set of values for any padding bits ([[basic.types.general]](#general "6.9.1 General"))
in the object representation are
alternative representations of the value specified by the value representation[.](#basic.fundamental-4.sentence-3)

[*Note [3](#basic.fundamental-note-3)*:

Padding bits have unspecified value, but cannot cause traps[.](#basic.fundamental-4.sentence-4)

In contrast, see ISO/IEC 9899:2024 6.2.6.2[.](#basic.fundamental-4.sentence-5)

â *end note*]

[*Note [4](#basic.fundamental-note-4)*:

The signed and unsigned integer types satisfy
the constraints given in ISO/IEC 9899:2024 5.2.4.2.1[.](#basic.fundamental-4.sentence-6)

â *end note*]

Except as specified above,
the width of a signed or unsigned integer type isimplementation-defined[.](#basic.fundamental-4.sentence-7)

[5](#basic.fundamental-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5405)

Each value x of an unsigned integer type with width N has
a unique representation x=x020+x121+â¦+xNâ12Nâ1,
where each coefficient xi is either 0 or 1;
this is called the [*base-2 representation*](#def:base-2_representation "6.9.2 Fundamental types [basic.fundamental]") of x[.](#basic.fundamental-5.sentence-1)

The base-2 representation of a value of signed integer type is
the base-2 representation of the congruent value
of the corresponding unsigned integer type[.](#basic.fundamental-5.sentence-2)

The standard signed integer types and standard unsigned integer types
are collectively called the [*standard integer types*](#def:type,standard_integer "6.9.2 Fundamental types [basic.fundamental]"), and the extended
signed integer types and extended
unsigned integer types are collectively called the[*extended integer types*](#def:type,extended_integer "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-5.sentence-3)

[6](#basic.fundamental-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5419)

A fundamental type specified to have
a signed or unsigned integer type as its [*underlying type*](#def:type,underlying "6.9.2 Fundamental types [basic.fundamental]") has
the same object representation,
value representation,
alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment")), and
range of representable values as the underlying type[.](#basic.fundamental-6.sentence-1)

Further, each value has the same representation in both types[.](#basic.fundamental-6.sentence-2)

[7](#basic.fundamental-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5428)

Type char is a distinct type
that has an implementation-defined choice of
âsigned charâ or âunsigned charâ as its underlying type[.](#basic.fundamental-7.sentence-1)

The three types char, signed char, and unsigned char are collectively called[*ordinary character types*](#def:type,ordinary_character "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-7.sentence-2)

The ordinary character types and char8_t are collectively called [*narrow character types*](#def:type,narrow_character "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-7.sentence-3)

For narrow character types,
each possible bit pattern of the object representation represents
a distinct value[.](#basic.fundamental-7.sentence-4)

[*Note [5](#basic.fundamental-note-5)*:

This requirement does not hold for other types[.](#basic.fundamental-7.sentence-5)

â *end note*]

[*Note [6](#basic.fundamental-note-6)*:

A bit-field of narrow character type whose width is larger than
the width of that type has padding bits; see [[basic.types.general]](#general "6.9.1 General")[.](#basic.fundamental-7.sentence-6)

â *end note*]

[8](#basic.fundamental-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5454)

Type wchar_t is a distinct type that has
an implementation-defined
signed or unsigned integer type as its underlying type[.](#basic.fundamental-8.sentence-1)

[9](#basic.fundamental-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5462)

Type char8_t denotes a distinct type
whose underlying type is unsigned char[.](#basic.fundamental-9.sentence-1)

Types char16_t and char32_t denote distinct types
whose underlying types are uint_least16_t and uint_least32_t,
respectively, in [<cstdint>](cstdint.syn#header:%3ccstdint%3e "17.4.1 Header <cstdint> synopsis [cstdint.syn]")[.](#basic.fundamental-9.sentence-2)

[10](#basic.fundamental-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5478)

Type bool is a distinct type that has
the same object representation,
value representation, and
alignment requirements as
an implementation-defined unsigned integer type[.](#basic.fundamental-10.sentence-1)

The values of type bool aretrue and false[.](#basic.fundamental-10.sentence-2)

[*Note [7](#basic.fundamental-note-7)*:

There are no signed, unsigned,short, or long bool types or values[.](#basic.fundamental-10.sentence-3)

â *end note*]

[11](#basic.fundamental-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5493)

The types char, wchar_t,char8_t, char16_t, and char32_t are collectively called [*character types*](#def:type,character "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-11.sentence-1)

The character types, bool,
the signed and unsigned integer types,
and cv-qualified versions ([[basic.type.qualifier]](#basic.type.qualifier "6.9.5 CV-qualifiers")) thereof,
are collectively termed[*integral types*](#def:integral_type "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-11.sentence-2)

A synonym for integral type is [*integer type*](#def:integer_type "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-11.sentence-3)

[*Note [8](#basic.fundamental-note-8)*:

Enumerations ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) are not integral;
however, unscoped enumerations can be promoted to integral types
as specified in [[conv.prom]](conv.prom "7.3.7 Integral promotions")[.](#basic.fundamental-11.sentence-4)

â *end note*]

[12](#basic.fundamental-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5510)

The three distinct typesfloat,double,
andlong double can represent floating-point numbers[.](#basic.fundamental-12.sentence-1)

The type double provides at least as much
precision as float, and the type long double provides at
least as much precision as double[.](#basic.fundamental-12.sentence-2)

The set of values of the typefloat is a subset of the set of values of the typedouble; the set of values of the type double is a subset
of the set of values of the type long double[.](#basic.fundamental-12.sentence-3)

The typesfloat, double, and long double,
and cv-qualified versions ([[basic.type.qualifier]](#basic.type.qualifier "6.9.5 CV-qualifiers")) thereof,
are collectively termed[*standard floating-point types*](#def:type,floating-point,standard "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-12.sentence-4)

An implementation may also provide additional types
that represent floating-point values and define them (and cv-qualified versions thereof) to be[*extended floating-point types*](#def:type,floating-point,extended "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-12.sentence-5)

The standard and extended floating-point types
are collectively termed [*floating-point types*](#def:type,floating-point "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-12.sentence-6)

[*Note [9](#basic.fundamental-note-9)*:

Any additional implementation-specific types representing floating-point values
that are not defined by the implementation to be extended floating-point types
are not considered to be floating-point types, and
this document imposes no requirements on them or
their interactions with floating-point types[.](#basic.fundamental-12.sentence-7)

â *end note*]

Except as specified in [[basic.extended.fp]](#basic.extended.fp "6.9.3 Optional extended floating-point types"),
the object and value representations and accuracy of operations
of floating-point types are implementation-defined[.](#basic.fundamental-12.sentence-8)

[13](#basic.fundamental-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5548)

The minimum range of representable values for a floating-point type is
the most negative finite floating-point number representable
in that type through
the most positive finite floating-point number representable in that type[.](#basic.fundamental-13.sentence-1)

In addition, if negative infinity is representable in a type,
the range of that type is extended to all negative real numbers;
likewise, if positive infinity is representable in a type,
the range of that type is extended to all positive real numbers[.](#basic.fundamental-13.sentence-2)

[*Note [10](#basic.fundamental-note-10)*:

Since negative and positive infinity are representable
in ISO/IEC 60559 formats,
all real numbers lie within the range of representable values of
a floating-point type adhering to ISO/IEC 60559[.](#basic.fundamental-13.sentence-3)

â *end note*]

[14](#basic.fundamental-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5564)

Integral and floating-point types are collectively
termed [*arithmetic types*](#def:type,arithmetic "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-14.sentence-1)

[*Note [11](#basic.fundamental-note-11)*:

Properties of the arithmetic types,
such as their minimum and maximum representable value,
can be queried using the facilities in the standard library headers[<limits>](limits.syn#header:%3climits%3e "17.3.3 Header <limits> synopsis [limits.syn]"),[<climits>](climits.syn#header:%3cclimits%3e "17.3.6 Header <climits> synopsis [climits.syn]"), and[<cfloat>](cfloat.syn#header:%3ccfloat%3e "17.3.7 Header <cfloat> synopsis [cfloat.syn]")[.](#basic.fundamental-14.sentence-2)

â *end note*]

[15](#basic.fundamental-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5576)

A type cv void is an incomplete type that cannot be completed; such a type has
an empty set of values[.](#basic.fundamental-15.sentence-1)

It is used as the return
type for functions that do not return a value[.](#basic.fundamental-15.sentence-2)

An expression of type cv void shall
be used only as

- [(15.1)](#basic.fundamental-15.1)

an expression statement ([[stmt.expr]](stmt.expr "8.3 Expression statement")),

- [(15.2)](#basic.fundamental-15.2)

the expression in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement"))
for a function with the return type cv void,

- [(15.3)](#basic.fundamental-15.3)

an operand of a comma expression ([[expr.comma]](expr.comma "7.6.20 Comma operator")),

- [(15.4)](#basic.fundamental-15.4)

the second or third operand of ?: ([[expr.cond]](expr.cond "7.6.16 Conditional operator")),

- [(15.5)](#basic.fundamental-15.5)

the operand of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),

- [(15.6)](#basic.fundamental-15.6)

the operand of a noexcept operator ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator")),

- [(15.7)](#basic.fundamental-15.7)

the operand of a decltype specifier ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers")), or

- [(15.8)](#basic.fundamental-15.8)

the operand of an explicit conversion to typecv void ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"))[.](#basic.fundamental-15.sentence-3)

[16](#basic.fundamental-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5597)

The types denoted by cv std​::​nullptr_t are distinct types[.](#basic.fundamental-16.sentence-1)

A prvalue of type std​::​nullptr_t is a null pointer
constant ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"))[.](#basic.fundamental-16.sentence-2)

Such values participate in the pointer and the
pointer-to-member conversions ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions"), [[conv.mem]](conv.mem "7.3.13 Pointer-to-member conversions"))[.](#basic.fundamental-16.sentence-3)

sizeof(std​::​nullptr_t) shall be equal to sizeof(void*)[.](#basic.fundamental-16.sentence-4)

[17](#basic.fundamental-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5604)

A value of type std​::​meta​::​info is called a [*reflection*](#def:reflection "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-17.sentence-1)

There exists a unique [*null reflection*](#def:reflection,null "6.9.2 Fundamental types [basic.fundamental]");
every other reflection is a representation of

- [(17.1)](#basic.fundamental-17.1)

a value of scalar type ([[temp.param]](temp.param "13.2 Template parameters")),

- [(17.2)](#basic.fundamental-17.2)

an object with static storage duration ([[basic.stc]](basic.stc "6.8.6 Storage duration")),

- [(17.3)](#basic.fundamental-17.3)

a variable ([[basic.pre]](basic.pre "6.1 Preamble")),

- [(17.4)](#basic.fundamental-17.4)

a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")),

- [(17.5)](#basic.fundamental-17.5)

a function ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),

- [(17.6)](#basic.fundamental-17.6)

a function parameter,

- [(17.7)](#basic.fundamental-17.7)

an enumerator ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")),

- [(17.8)](#basic.fundamental-17.8)

an annotation ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics")),

- [(17.9)](#basic.fundamental-17.9)

a type alias ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),

- [(17.10)](#basic.fundamental-17.10)

a type ([basic.types]),

- [(17.11)](#basic.fundamental-17.11)

a class member ([[class.mem]](class.mem "11.4 Class members")),

- [(17.12)](#basic.fundamental-17.12)

an unnamed bit-field ([[class.bit]](class.bit "11.4.10 Bit-fields")),

- [(17.13)](#basic.fundamental-17.13)

a class template ([[temp.pre]](temp.pre "13.1 Preamble")),

- [(17.14)](#basic.fundamental-17.14)

a function template,

- [(17.15)](#basic.fundamental-17.15)

a variable template,

- [(17.16)](#basic.fundamental-17.16)

an alias template ([[temp.alias]](temp.alias "13.7.8 Alias templates")),

- [(17.17)](#basic.fundamental-17.17)

a concept ([[temp.concept]](temp.concept "13.7.9 Concept definitions")),

- [(17.18)](#basic.fundamental-17.18)

a namespace alias ([[namespace.alias]](namespace.alias "9.9.3 Namespace alias")),

- [(17.19)](#basic.fundamental-17.19)

a namespace ([[basic.namespace.general]](basic.namespace.general "9.9.1 General")),

- [(17.20)](#basic.fundamental-17.20)

a direct base class relationship ([[class.derived.general]](class.derived.general "11.7.1 General")), or

- [(17.21)](#basic.fundamental-17.21)

a data member description ([[class.mem.general]](class.mem.general "11.4.1 General"))[.](#basic.fundamental-17.sentence-2)

A reflection is said to [*represent*](#def:represent "6.9.2 Fundamental types [basic.fundamental]") the corresponding construct[.](#basic.fundamental-17.sentence-3)

[*Note [12](#basic.fundamental-note-12)*:

A reflection of a value can be produced by library functions such asstd​::​meta​::​constant_of and std​::​meta​::​reflect_constant[.](#basic.fundamental-17.sentence-4)

â *end note*]

[*Example [2](#basic.fundamental-example-2)*: int arr[] = {1, 2, 3};auto [a1, a2, a3] = arr;void fn();enum Enum { A };using Alias = int;struct B {};struct S : B {int mem; int : 0;};template<auto> struct TCls {};template<auto> void TFn();template<auto> int TVar;template<auto> concept Concept = requires { true; };namespace NS {};namespace NSAlias = NS;

constexpr auto ctx = std::meta::access_context::current();

constexpr auto r1 = std::meta::reflect_constant(42); // represents int value of 42constexpr auto r2 = std::meta::reflect_object(arr[1]); // represents int objectconstexpr auto r3 = ^^arr; // represents a variableconstexpr auto r4 = ^^a3; // represents a structured bindingconstexpr auto r5 = ^^fn; // represents a functionconstexpr auto r6 = ^^Enum::A; // represents an enumeratorconstexpr auto r7 = ^^Alias; // represents a type aliasconstexpr auto r8 = ^^S; // represents a typeconstexpr auto r9 = ^^S::mem; // represents a class memberconstexpr auto r10 = std::meta::members_of(^^S, ctx)[1]; // represents an unnamed bit-fieldconstexpr auto r11 = ^^TCls; // represents a class templateconstexpr auto r12 = ^^TFn; // represents a function templateconstexpr auto r13 = ^^TVar; // represents a variable templateconstexpr auto r14 = ^^Concept; // represents a conceptconstexpr auto r15 = ^^NSAlias; // represents a namespace aliasconstexpr auto r16 = ^^NS; // represents a namespaceconstexpr auto r17 = std::meta::bases_of(^^S, ctx)[0]; // represents a direct base class relationshipconstexpr auto r18 = std::meta::data_member_spec(^^int, {.name="member"}); // represents a data member description â *end example*]

[18](#basic.fundamental-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5679)

*Recommended practice*: Implementations should not represent other constructs
specified in this document, such as[*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]")*s*,
partial template specializations,
attributes, placeholder types,
statements, or
expressions,
as values of type std​::​meta​::​info[.](#basic.fundamental-18.sentence-1)

[*Note [13](#basic.fundamental-note-13)*:

Future revisions of this document can specify semantics for reflections
representing any such constructs[.](#basic.fundamental-18.sentence-2)

â *end note*]

[19](#basic.fundamental-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5694)

The types described in this subclause
are called [*fundamental types*](#def:fundamental_type "6.9.2 Fundamental types [basic.fundamental]")[.](#basic.fundamental-19.sentence-1)

[*Note [14](#basic.fundamental-note-14)*:

Even if the implementation defines two or more fundamental types to have the
same value representation, they are nevertheless different types[.](#basic.fundamental-19.sentence-2)

â *end note*]

[30)](#footnote-30)[30)](#footnoteref-30)

This
is also known as two's complement representation[.](#footnote-30.sentence-1)

### [6.9.3](#basic.extended.fp) Optional extended floating-point types [[basic.extended.fp]](basic.extended.fp)

[1](#basic.extended.fp-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5705)

If the implementation supports an extended floating-point type ([[basic.fundamental]](#basic.fundamental "6.9.2 Fundamental types"))
whose properties are specified by
the ISO/IEC 60559 floating-point interchange format binary16,
then the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std​::​float16_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
the macro __STDCPP_FLOAT16_T__ is defined ([[cpp.predefined]](cpp.predefined "15.12 Predefined macro names")), and
the floating-point literal suffixes f16 and F16 are supported ([[lex.fcon]](lex.fcon "5.13.4 Floating-point literals"))[.](#basic.extended.fp-1.sentence-1)

[2](#basic.extended.fp-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5715)

If the implementation supports an extended floating-point type
whose properties are specified by
the ISO/IEC 60559 floating-point interchange format binary32,
then the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std​::​float32_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
the macro __STDCPP_FLOAT32_T__ is defined, and
the floating-point literal suffixes f32 and F32 are supported[.](#basic.extended.fp-2.sentence-1)

[3](#basic.extended.fp-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5724)

If the implementation supports an extended floating-point type
whose properties are specified by
the ISO/IEC 60559 floating-point interchange format binary64,
then the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std​::​float64_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
the macro __STDCPP_FLOAT64_T__ is defined, and
the floating-point literal suffixes f64 and F64 are supported[.](#basic.extended.fp-3.sentence-1)

[4](#basic.extended.fp-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5733)

If the implementation supports an extended floating-point type
whose properties are specified by
the ISO/IEC 60559 floating-point interchange format binary128,
then the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std​::​float128_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
the macro __STDCPP_FLOAT128_T__ is defined, and
the floating-point literal suffixes f128 and F128 are supported[.](#basic.extended.fp-4.sentence-1)

[5](#basic.extended.fp-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5742)

If the implementation supports an extended floating-point type
with the properties, as specified by ISO/IEC 60559, of
radix (b) of 2,
storage width in bits (k) of 16,
precision in bits (p) of 8,
maximum exponent (emax) of 127, and
exponent field width in bits (w) of 8, then
the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std​::​bfloat16_t is declared in the header [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") and names such a type,
the macro __STDCPP_BFLOAT16_T__ is defined, and
the floating-point literal suffixes bf16 and BF16 are supported[.](#basic.extended.fp-5.sentence-1)

[6](#basic.extended.fp-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5755)

[*Note [1](#basic.extended.fp-note-1)*:

A summary of the parameters for each type is given in Table [15](#tab:basic.extended.fp "Table 15: Properties of named extended floating-point types")[.](#basic.extended.fp-6.sentence-1)

The precision p includes the implicit 1 bit at the beginning of the significand,
so the storage used for the significand is pâ1 bits[.](#basic.extended.fp-6.sentence-2)

ISO/IEC 60559 does not assign a name for a type
having the parameters specified for std​::​bfloat16_t[.](#basic.extended.fp-6.sentence-3)

â *end note*]

Table [15](#tab:basic.extended.fp) — Properties of named extended floating-point types [[tab:basic.extended.fp]](./tab:basic.extended.fp)  

| [ð](#tab:basic.extended.fp-row-1)<br>**Parameter** | **float16_t** | **float32_t** | **float64_t** | **float128_t** | **bfloat16_t** |
| --- | --- | --- | --- | --- | --- |
| [ð](#tab:basic.extended.fp-row-2)<br>ISO/IEC 60559 name | binary16 | binary32 | binary64 | binary128 |  |
| [ð](#tab:basic.extended.fp-row-3)<br>k, storage width in bits | 16 | 32 | 64 | 128 | 16 |
| [ð](#tab:basic.extended.fp-row-4)<br>p, precision in bits | 11 | 24 | 53 | 113 | 8 |
| [ð](#tab:basic.extended.fp-row-5)<br>emax, maximum exponent | 15 | 127 | 1023 | 16383 | 127 |
| [ð](#tab:basic.extended.fp-row-6)<br>w, exponent field width in bits | 5 | 8 | 11 | 15 | 8 |

[7](#basic.extended.fp-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5777)

*Recommended practice*: Any names that the implementation provides for
the extended floating-point types described in this subsection
that are in addition to the names declared in the [<stdfloat>](stdfloat.syn#header:%3cstdfloat%3e "17.4.2 Header <stdfloat> synopsis [stdfloat.syn]") header
should be chosen to increase compatibility and interoperability
with the interchange types_Float16, _Float32, _Float64, and _Float128 defined in ISO/IEC TS 18661-3 and with future versions of ISO/IEC 9899[.](#basic.extended.fp-7.sentence-1)

### [6.9.4](#basic.compound) Compound types [[basic.compound]](basic.compound)

[1](#basic.compound-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5789)

Compound types can be constructed in the following ways:

- [(1.1)](#basic.compound-1.1)

  [*arrays*](#def:type,array "6.9.4 Compound types [basic.compound]") of objects of a given type, [[dcl.array]](dcl.array "9.3.4.5 Arrays");

- [(1.2)](#basic.compound-1.2)

  [*functions*](dcl.fct#def:type,function "9.3.4.6 Functions [dcl.fct]"), which have parameters of given types and returnvoid or a result of a given type, [[dcl.fct]](dcl.fct "9.3.4.6 Functions");

- [(1.3)](#basic.compound-1.3)

  [*pointers*](#def:type,pointer "6.9.4 Compound types [basic.compound]") to cv void or objects or functions (including
static members of classes) of a given type, [[dcl.ptr]](dcl.ptr "9.3.4.2 Pointers");

- [(1.4)](#basic.compound-1.4)

  [*references*](#def:reference "6.9.4 Compound types [basic.compound]") to objects or functions of a given
type, [[dcl.ref]](dcl.ref "9.3.4.3 References")[.](#basic.compound-1.4.sentence-1)
  There are two types of references:
  * [(1.4.1)](#basic.compound-1.4.1)

lvalue reference

  * [(1.4.2)](#basic.compound-1.4.2)

rvalue reference

- [(1.5)](#basic.compound-1.5)

  [*classes*](#def:class "6.9.4 Compound types [basic.compound]") containing a sequence of class members ([[class]](class "11 Classes"), [[class.mem]](class.mem "11.4 Class members")),
and a set of restrictions
on the access to these entities ([[class.access]](class.access "11.8 Member access control"));

- [(1.6)](#basic.compound-1.6)

  [*unions*](#def:union "6.9.4 Compound types [basic.compound]"), which are classes capable of containing objects of
different types at different times, [[class.union]](class.union "11.5 Unions");

- [(1.7)](#basic.compound-1.7)

  [*enumerations*](#def:enum "6.9.4 Compound types [basic.compound]"),
which comprise a set of named constant values, [[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations");

- [(1.8)](#basic.compound-1.8)

  [*pointers to non-static class members*](#def:pointer_to_member "6.9.4 Compound types [basic.compound]"),[31](#footnote-31 "Static class members are objects or functions, and pointers to them are ordinary pointers to objects or functions.") which identify members of a given
type within objects of a given class, [[dcl.mptr]](dcl.mptr "9.3.4.4 Pointers to members")[.](#basic.compound-1.8.sentence-1)
  Pointers to data members and pointers to member functions are collectively
called [*pointer-to-member*](#def:pointer-to-member "6.9.4 Compound types [basic.compound]") types[.](#basic.compound-1.8.sentence-2)

[2](#basic.compound-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5837)

These methods of constructing types can be applied recursively;
restrictions are mentioned in [[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators")[.](#basic.compound-2.sentence-1)

Constructing a type such that the number of
bytes in its object representation exceeds the maximum value representable in
the type std​::​size_t ([[support.types]](support.types "17.2 Common definitions")) is ill-formed[.](#basic.compound-2.sentence-2)

[3](#basic.compound-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5844)

The type of a pointer to cv void or a pointer to an object type is
called an [*object pointer type*](#def:object_pointer_type "6.9.4 Compound types [basic.compound]")[.](#basic.compound-3.sentence-1)

[*Note [1](#basic.compound-note-1)*:

A pointer to void does not have a pointer-to-object type, however, because void is not
an object type[.](#basic.compound-3.sentence-2)

â *end note*]

The type of a pointer that can designate a function
is called a [*function pointer type*](#def:function_pointer_type "6.9.4 Compound types [basic.compound]")[.](#basic.compound-3.sentence-3)

A pointer to an object of type T is referred to as a âpointer toTâ[.](#basic.compound-3.sentence-4)

[*Example [1](#basic.compound-example-1)*:

A pointer to an object of type int is
referred to as âpointer to intâ and a pointer to an object of
class X is called a âpointer to Xâ[.](#basic.compound-3.sentence-5)

â *end example*]

Except for pointers to static members, text referring to âpointersâ
does not apply to pointers to members[.](#basic.compound-3.sentence-6)

Pointers to incomplete types are
allowed although there are restrictions on what can be done with
them ([[basic.types.general]](#general "6.9.1 General"))[.](#basic.compound-3.sentence-7)

Every value of pointer type is one of the following:

- [(3.1)](#basic.compound-3.1)

a [*pointer to*](#def:pointer_to "6.9.4 Compound types [basic.compound]") an object or function (the pointer is said to [*point*](#def:point "6.9.4 Compound types [basic.compound]") to the object or function), or

- [(3.2)](#basic.compound-3.2)

a [*pointer past the end of*](#def:pointer_past_the_end_of "6.9.4 Compound types [basic.compound]") an object ([[expr.add]](expr.add "7.6.6 Additive operators")), or

- [(3.3)](#basic.compound-3.3)

the [*null pointer value*](#def:value,null_pointer "6.9.4 Compound types [basic.compound]") for that type, or

- [(3.4)](#basic.compound-3.4)

an [*invalid pointer value*](#def:value,invalid_pointer "6.9.4 Compound types [basic.compound]")[.](#basic.compound-3.sentence-8)

A value of a
pointer type
that is a pointer to or past the end of an object[*represents the address*](#def:represents_the_address "6.9.4 Compound types [basic.compound]") of
the first byte in memory ([[intro.memory]](intro.memory "6.8.1 Memory model")) occupied by the object[32](#footnote-32 "For an object that is not within its lifetime, this is the first byte in memory that it will occupy or used to occupy.") or the first byte in memory
after the end of the storage occupied by the object,
respectively[.](#basic.compound-3.sentence-9)

[*Note [2](#basic.compound-note-2)*:

A pointer past the end of an object ([[expr.add]](expr.add "7.6.6 Additive operators"))
is not considered to point to an unrelated object
of the object's type,
even if the unrelated object is located at that address[.](#basic.compound-3.sentence-10)

â *end note*]

For purposes of pointer arithmetic ([[expr.add]](expr.add "7.6.6 Additive operators"))
and comparison ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators")),
a pointer past the end of the last element of
an array x of n elements
is considered to be equivalent to
a pointer to a hypothetical array element n of x, and
an object of type T that is not an array element
is considered to belong to an array with one element of type T[.](#basic.compound-3.sentence-11)

The value representation of
pointer types is implementation-defined[.](#basic.compound-3.sentence-12)

Pointers to
layout-compatible types shall
have the same value representation and alignment
requirements ([[basic.align]](basic.align "6.8.3 Alignment"))[.](#basic.compound-3.sentence-13)

[*Note [3](#basic.compound-note-3)*:

Pointers to [over-aligned types](basic.align#def:type,over-aligned "6.8.3 Alignment [basic.align]") have no special
representation, but their range of valid values is restricted by the extended
alignment requirement[.](#basic.compound-3.sentence-14)

â *end note*]

[4](#basic.compound-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5917)

A pointer value P is[*valid in the context of*](#def:valid_in_the_context_of "6.9.4 Compound types [basic.compound]") an evaluation E if P is a pointer to function or a null pointer value, or
if it is a pointer to or past the end of an object O andE happens before the end of the duration of the region of storage for O[.](#basic.compound-4.sentence-1)

If a pointer value P is used in an evaluation E andP is not valid in the context of E,
then the behavior is undefined if E is
an indirection ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")) or
an invocation of a deallocation function ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions")),
and implementation-defined otherwise[.](#basic.compound-4.sentence-2)[33](#footnote-33 "Some implementations might define that copying such a pointer value causes a system-generated runtime fault.")

[*Note [4](#basic.compound-note-4)*:

P can be valid in the context of E even
if it points to a type unrelated to that of O or
if O is not within its lifetime,
although further restrictions apply
to such pointer values ([[basic.life]](basic.life "6.8.4 Lifetime"), [[basic.lval]](basic.lval "7.2.1 Value category"), [[expr.add]](expr.add "7.6.6 Additive operators"))[.](#basic.compound-4.sentence-3)

â *end note*]

[5](#basic.compound-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5942)

Two objects *a* and *b* are [*pointer-interconvertible*](#def:pointer-interconvertible "6.9.4 Compound types [basic.compound]") if

- [(5.1)](#basic.compound-5.1)

they are the same object, or

- [(5.2)](#basic.compound-5.2)

one is a union object and
the other is a non-static data member of that object ([[class.union]](class.union "11.5 Unions")), or

- [(5.3)](#basic.compound-5.3)

one is a standard-layout class object and
the other is the first non-static data member of that object or
any base class subobject of that object ([[class.mem]](class.mem "11.4 Class members")), or

- [(5.4)](#basic.compound-5.4)

there exists an object *c* such that*a* and *c* are pointer-interconvertible, and*c* and *b* are pointer-interconvertible[.](#basic.compound-5.sentence-1)

If two objects are pointer-interconvertible,
then they have the same address,
and it is possible to obtain a pointer to one
from a pointer to the other
via a reinterpret_cast ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"))[.](#basic.compound-5.sentence-2)

[*Note [5](#basic.compound-note-5)*:

An array object and its first element are not pointer-interconvertible,
even though they have the same address[.](#basic.compound-5.sentence-3)

â *end note*]

[6](#basic.compound-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5969)

A byte of storage *b* is [*reachable through*](#def:storage,reachable_through_a_pointer_value "6.9.4 Compound types [basic.compound]") a pointer value that points to an object *x* if there is an object *y*,
pointer-interconvertible with *x*,
such that *b* is within the storage occupied by*y*, or the immediately-enclosing array object
if *y* is an array element[.](#basic.compound-6.sentence-1)

[7](#basic.compound-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5979)

A pointer to cv void can be used to point to objects of
unknown type[.](#basic.compound-7.sentence-1)

Such a pointer shall be able to hold any object pointer[.](#basic.compound-7.sentence-2)

An object of type âpointer to cv voidâ
shall have the same representation and alignment
requirements as an object of type âpointer to cv charâ[.](#basic.compound-7.sentence-3)

[31)](#footnote-31)[31)](#footnoteref-31)

Static class members are objects or functions, and pointers to them are
ordinary pointers to objects or functions[.](#footnote-31.sentence-1)

[32)](#footnote-32)[32)](#footnoteref-32)

For an object that is not within its lifetime,
this is the first byte in memory that it will occupy or used to occupy[.](#footnote-32.sentence-1)

[33)](#footnote-33)[33)](#footnoteref-33)

Some implementations might define that
copying such a pointer value causes a system-generated runtime fault[.](#footnote-33.sentence-1)

### [6.9.5](#basic.type.qualifier) CV-qualifiers [[basic.type.qualifier]](basic.type.qualifier)

[1](#basic.type.qualifier-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L5991)

Each type other than a function or reference type
is part of a group of four distinct, but related, types:
a [*cv-unqualified*](#def:cv-unqualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version,
a [*const-qualified*](#def:const-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version,
a [*volatile-qualified*](#def:volatile-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version, and
a [*const-volatile-qualified*](#def:const-volatile-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") version[.](#basic.type.qualifier-1.sentence-1)

The types in each such group shall have
the same representation and alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment"))[.](#basic.type.qualifier-1.sentence-2)[34](#footnote-34 "The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and non-static data members of unions.")

A function or reference type is always cv-unqualified[.](#basic.type.qualifier-1.sentence-3)

- [(1.1)](#basic.type.qualifier-1.1)

  A [*const object*](#def:object,const "6.9.5 CV-qualifiers [basic.type.qualifier]") is an object of type const T or a
 non-mutable subobject of a const object[.](#basic.type.qualifier-1.1.sentence-1)

- [(1.2)](#basic.type.qualifier-1.2)

  A [*volatile object*](#def:object,volatile "6.9.5 CV-qualifiers [basic.type.qualifier]") is an object of type volatile T or a subobject of a volatile object[.](#basic.type.qualifier-1.2.sentence-1)

- [(1.3)](#basic.type.qualifier-1.3)

  A [*const volatile object*](#def:object,const_volatile "6.9.5 CV-qualifiers [basic.type.qualifier]") is an object of type const volatile T, a non-mutable subobject of a const volatile object,
 a const subobject of a volatile object, or a non-mutable volatile
 subobject of a const object[.](#basic.type.qualifier-1.3.sentence-1)

[*Note [1](#basic.type.qualifier-note-1)*:

The type of an object ([[intro.object]](intro.object "6.8.2 Object model")) includes
the [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* specified in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") ([[dcl.spec]](dcl.spec "9.2 Specifiers")),[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3 Declarators")),[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ([[dcl.name]](dcl.name "9.3.2 Type names")), or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))
when the object is created[.](#basic.type.qualifier-1.sentence-4)

â *end note*]

[2](#basic.type.qualifier-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6033)

Except for array types, a compound type ([[basic.compound]](#basic.compound "6.9.4 Compound types")) is not cv-qualified by the
cv-qualifiers (if any) of the types from which it is compounded[.](#basic.type.qualifier-2.sentence-1)

[3](#basic.type.qualifier-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6037)

An array type whose elements are cv-qualified
is also considered to have the same cv-qualifications
as its elements[.](#basic.type.qualifier-3.sentence-1)

[*Note [2](#basic.type.qualifier-note-2)*:

Cv-qualifiers applied to an array
type attach to the underlying element type, so the notation
âcv Tâ, where T is an array type, refers to
an array whose elements are so-qualified ([[dcl.array]](dcl.array "9.3.4.5 Arrays"))[.](#basic.type.qualifier-3.sentence-2)

â *end note*]

[*Example [1](#basic.type.qualifier-example-1)*: typedef char CA[5];typedef const char CC;
CC arr1[5] = { 0 };const CA arr2 = { 0 };

The type of both arr1 and arr2 is âarray of 5const charâ, and the array type is considered to be
const-qualified[.](#basic.type.qualifier-3.sentence-3)

â *end example*]

[4](#basic.type.qualifier-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6061)

[*Note [3](#basic.type.qualifier-note-3)*:

See [[dcl.fct]](dcl.fct "9.3.4.6 Functions") and [[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists") regarding function
types that have [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*[.](#basic.type.qualifier-4.sentence-1)

â *end note*]

[5](#basic.type.qualifier-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6067)

There is a partial ordering on cv-qualifiers, so that a type can be
said to be [*more cv-qualified*](#def:more_cv-qualified "6.9.5 CV-qualifiers [basic.type.qualifier]") than another[.](#basic.type.qualifier-5.sentence-1)

Table [16](#tab:basic.type.qualifier.rel "Table 16: Relations on const and volatile") shows the relations that
constitute this ordering[.](#basic.type.qualifier-5.sentence-2)

Table [16](#tab:basic.type.qualifier.rel) — Relations on const and volatile [[tab:basic.type.qualifier.rel]](./tab:basic.type.qualifier.rel)  

| [ð](#tab:basic.type.qualifier.rel-row-1)<br>*no cv-qualifier* | < | const |
| --- | --- | --- |
| [ð](#tab:basic.type.qualifier.rel-row-2)<br>*no cv-qualifier* | < | volatile |
| [ð](#tab:basic.type.qualifier.rel-row-3)<br>*no cv-qualifier* | < | const volatile |
| [ð](#tab:basic.type.qualifier.rel-row-4)<br>const | < | const volatile |
| [ð](#tab:basic.type.qualifier.rel-row-5)<br>volatile | < | const volatile |

[6](#basic.type.qualifier-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6083)

In this document, the notation cv (or*cv1*, *cv2*, etc[.](#basic.type.qualifier-6.sentence-1))

, used in the description of types,
represents an arbitrary set of cv-qualifiers, i.e., one of
{const}, {volatile}, {const,volatile}, or the empty set[.](#basic.type.qualifier-6.sentence-2)

For a type cv T, the [*top-level cv-qualifiers*](#def:cv-qualifier,top-level "6.9.5 CV-qualifiers [basic.type.qualifier]") of that type are those denoted by cv[.](#basic.type.qualifier-6.sentence-3)

[*Example [2](#basic.type.qualifier-example-2)*:

The type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")const int& has no top-level cv-qualifiers[.](#basic.type.qualifier-6.sentence-4)

The type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")volatile int * const has the top-level cv-qualifier const[.](#basic.type.qualifier-6.sentence-5)

For a class type C,
the type corresponding to the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")void (C​::​* volatile)(int) const has the top-level cv-qualifier volatile[.](#basic.type.qualifier-6.sentence-6)

â *end example*]

[34)](#footnote-34)[34)](#footnoteref-34)

The same representation and alignment requirements
are meant to imply interchangeability as
arguments to functions,
return values from functions, and
non-static data members of unions[.](#footnote-34.sentence-1)

### [6.9.6](#conv.rank) Conversion ranks [[conv.rank]](conv.rank)

[1](#conv.rank-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6107)

Every integer type has an [*integer conversion rank*](#def:integer_conversion_rank) defined as follows:

- [(1.1)](#conv.rank-1.1)

  No two signed integer types other than char and signedchar (if char is signed) have the same rank, even if they have
the same representation[.](#conv.rank-1.1.sentence-1)

- [(1.2)](#conv.rank-1.2)

  The rank of a signed integer type is greater than the rank
of any signed integer type with a smaller width[.](#conv.rank-1.2.sentence-1)

- [(1.3)](#conv.rank-1.3)

  The rank of long long int is greater
than the rank of long int, which is greater than
the rank of int, which is greater than the rank ofshort int, which is greater than the rank ofsigned char[.](#conv.rank-1.3.sentence-1)

- [(1.4)](#conv.rank-1.4)

  The rank of any unsigned integer type equals the rank of the
corresponding signed integer type[.](#conv.rank-1.4.sentence-1)

- [(1.5)](#conv.rank-1.5)

  The rank of any standard integer type is greater than the
rank of any extended integer type with the same width[.](#conv.rank-1.5.sentence-1)

- [(1.6)](#conv.rank-1.6)

  The rank of char equals the rank of signed char and unsigned char[.](#conv.rank-1.6.sentence-1)

- [(1.7)](#conv.rank-1.7)

  The rank of bool is less than the rank of all
standard integer types[.](#conv.rank-1.7.sentence-1)

- [(1.8)](#conv.rank-1.8)

  The ranks of char8_t, char16_t, char32_t, andwchar_t equal the ranks of their underlying
types ([[basic.fundamental]](#basic.fundamental "6.9.2 Fundamental types"))[.](#conv.rank-1.8.sentence-1)

- [(1.9)](#conv.rank-1.9)

  The rank of any extended signed integer type relative to another
extended signed integer type with the same width is implementation-defined, but still subject to the other rules for determining the integer
conversion rank[.](#conv.rank-1.9.sentence-1)

- [(1.10)](#conv.rank-1.10)

  For all integer types T1, T2, and T3, ifT1 has greater rank than T2 and T2 has greater
rank than T3, then T1 has greater rank thanT3[.](#conv.rank-1.10.sentence-1)

[*Note [1](#conv.rank-note-1)*:

The integer conversion rank is used in the definition of the integral
promotions ([[conv.prom]](conv.prom "7.3.7 Integral promotions")) and the usual arithmetic
conversions ([[expr.arith.conv]](expr.arith.conv "7.4 Usual arithmetic conversions"))[.](#conv.rank-1.sentence-2)

â *end note*]

[2](#conv.rank-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6160)

Every floating-point type has a [*floating-point conversion rank*](#def:conversion_rank,floating-point "6.9.6 Conversion ranks [conv.rank]") defined as follows:

- [(2.1)](#conv.rank-2.1)

  The rank of a floating point type T is greater than
the rank of any floating-point type
whose set of values is a proper subset of the set of values of T[.](#conv.rank-2.1.sentence-1)

- [(2.2)](#conv.rank-2.2)

  The rank of long double is greater than
the rank of double,
which is greater than the rank of float[.](#conv.rank-2.2.sentence-1)

- [(2.3)](#conv.rank-2.3)

  Two extended floating-point types with the same set of values have equal ranks[.](#conv.rank-2.3.sentence-1)

- [(2.4)](#conv.rank-2.4)

  An extended floating-point type with the same set of values as
exactly one cv-unqualified standard floating-point type
has a rank equal to the rank of that standard floating-point type[.](#conv.rank-2.4.sentence-1)

- [(2.5)](#conv.rank-2.5)

  An extended floating-point type with the same set of values as
more than one cv-unqualified standard floating-point type
has a rank equal to the rank of double[.](#conv.rank-2.5.sentence-1)
  [*Note [2](#conv.rank-note-2)*:
  The treatment of std​::​float64_t differs from
that of the analogous _Float64 in C,
for example on platforms where all oflong double,double, andstd​::​float64_t have the same set of values (see ISO/IEC 9899:2024 H.4.2)[.](#conv.rank-2.5.sentence-2)
 â *end note*]

[*Note [3](#conv.rank-note-3)*:

The conversion ranks of floating-point types T1 and T2 are unordered if the set of values of T1 is
neither a subset nor a superset of the set of values of T2[.](#conv.rank-2.sentence-2)

This can happen when one type has both a larger range and a lower precision
than the other[.](#conv.rank-2.sentence-3)

â *end note*]

[3](#conv.rank-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6200)

Floating-point types that have equal floating-point conversion ranks
are ordered by floating-point conversion subrank[.](#conv.rank-3.sentence-1)

The subrank forms a total order among types with equal ranks[.](#conv.rank-3.sentence-2)

The typesstd​::​float16_t,std​::​float32_t,std​::​float64_t, andstd​::​float128_t ([[stdfloat.syn]](stdfloat.syn "17.4.2 Header <stdfloat> synopsis"))
have a greater conversion subrank than any standard floating-point type
with equal conversion rank[.](#conv.rank-3.sentence-3)

Otherwise, the conversion subrank order isimplementation-defined[.](#conv.rank-3.sentence-4)

[4](#conv.rank-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L6214)

[*Note [4](#conv.rank-note-4)*:

The floating-point conversion rank and subrank are used in
the definition of the usual arithmetic conversions ([[expr.arith.conv]](expr.arith.conv "7.4 Usual arithmetic conversions"))[.](#conv.rank-4.sentence-1)

â *end note*]
