C++ Core Types
void
void: type with an empty set of values. It is an incomplete type that cannot be completed (consequently, objects of type void are disallowed). There are no arrays of void, nor references to void. However, pointers to void and functions returning type void (procedures in other languages) are permitted.
std::nullptr_t
(Defined in header <cstddef>
)
typedef decltype(nullptr) nullptr_t;(since C++11)
std::nullptr_t
is the type of the null pointer literal, nullptr
. It is a distinct type that is not itself a pointer type or a pointer to member type. All Its prvalues are null pointer constants.
sizeof(std::nullptr_t)
is equal tosizeof(void*)
.
C++ Built-in Integer Types
Standard integer types
int: basic integer type. The keyword int
may be omitted if any of the modifiers listed below are used. If no length modifiers are present, it's guaranteed to have a width of at least 16 bits. However, on 32/64 bit systems it is almost exclusively guaranteed to have width of at least 32 bits (see below).
Modifiers
They modify the basic integer type. Can be mixed in any order. Only one of each group can be present in type name.
- Signedness:
-
signed: target type will have signed representation (this is the default if omitted)
unsigned: target type will have unsigned representation
- Size:
-
short: target type will be optimized for space and will have width of at least 16 bits.
long: target type will have width of at least 32 bits.
long long: (since C++11) target type will have width of at least 64 bits.
Note: as with all type specifiers, any order is permitted: unsigned long long int and long int unsigned long name the same type.
std::size_t is the unsigned integer type of the result of the sizeof operator as well as the sizeof... operator and the alignof operator(since C++11).
Extended integer types
The extended integer types are implementation-defined. Note that fixed width integer types are typically aliases of the standard integer types.
Boolean Type
bool: integer type, capable of holding one of the two values: true or false. The value of sizeof(bool) is implementation defined and might differ from 1.
C++ Built-in Character Types
Character types are integer types used for a character representation.
- signed char: type for signed character representation.
- unsigned char: type for unsigned character representation. Also used to inspect object representations (raw memory).
- char: type for character representation which can be most efficiently processed on the target system (has the same representation and alignment as either signed char or unsigned char, but is always a distinct type). Multibyte characters strings use this type to represent code units. For every value of type unsigned char in range [0, 255], converting the value to char and then back to unsigned char produces the original value.(since C++11) The signedness of char depends on the compiler and the target platform: the defaults for ARM and PowerPC are typically unsigned, the defaults for x86 and x64 are typically signed.
- wchar_t: type for wide character representation (see wide strings). It has the same size, signedness, and alignment as one of the integer types, but is a distinct type. In practice, it is 32 bits and holds UTF-32 on Linux and many other non-Windows systems, but 16 bits and holds UTF-16 code units on Windows. The standard used to require wchar_t to be large enough to represent any supported character code point. However, such requirement cannot be fulfilled on Windows, and thus it is considered as a defect and removed.
Types added in C++11:
- char16_t: type for UTF-16 character representation, required to be large enough to represent any UTF-16 code unit (16 bits). It has the same size, signedness, and alignment as std::uint_least16_t, but is a distinct type.
- char32_t: type for UTF-32 character representation, required to be large enough to represent any UTF-32 code unit (32 bits). It has the same size, signedness, and alignment as std::uint_least32_t, but is a distinct type.
Type added in C++20:
- char8_t type for UTF-8 character representation, required to be large enough to represent any UTF-8 code unit (8 bits). It has the same size, signedness, and alignment as unsigned char (and therefore, the same size and alignment as char and signed char), but is a distinct type.
Besides the minimal bit counts, the C++ Standard guarantees that
1 == sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long).
Note: this allows the extreme case in which bytes are sized 64 bits, all types (including char) are 64 bits wide, and sizeof returns 1 for every type.
C++ Built-in Floating Point Types
Standard floating-point types
The following three types and their cv-qualified versions are collectively called standard floating-point types.
- float: single precision floating-point type. Usually IEEE-754 binary32 format.
- double: double precision floating-point type. Usually IEEE-754 binary64 format.
- long double: extended precision floating-point type. Does not necessarily map to types mandated by IEEE-754.
Extended floating-point types
The extended floating-point types are implementation-defined. They may include fixed width floating-point types.
Removing Constantness, Reference-ness, Pointer-ness from Types
Constantness, Reference-ness, Pointer-ness can be removed from a type through:
std::remove_const
std::remove_reference
std::remove_pointer
: obtains the type pointed by T (if T is a pointer)std::decay
The stripped type is available as a member alias named value
.
For each of these struct's there is a reverse one that adds a feature instead of removing it.
add_const
add_pointer
add_lvalue_reference
add_rvalue_reference
add_volatile
add_cv
: obtains the type T with both const and volatile qualification
Removing Reference-ness with std::remove_reference
Obtains the non-reference type to which T refers. The transformed type is aliased as member type remove_reference::type
.
If T is a reference type (either lvalue reference or rvalue reference), this is the type to which it refers. Otherwise, it is the same as T, unchanged.
Notice that this class merely obtains a type using another type as model, but it does not transform values or objects between those types.
An example:
#include <iostream> #include <type_traits> int main() { typedef int&& rval_int; typedef std::remove_reference<int>::type A; typedef std::remove_reference<int&>::type B; typedef std::remove_reference<int&&>::type C; typedef std::remove_reference<rval_int>::type D; std::cout << std::boolalpha; std::cout << "typedefs of int:" << std::endl; std::cout << "A: " << std::is_same<int,A>::value << std::endl; std::cout << "B: " << std::is_same<int,B>::value << std::endl; std::cout << "C: " << std::is_same<int,C>::value << std::endl; std::cout << "D: " << std::is_same<int,D>::value << std::endl; return 0; }
Its output:
typedefs of int: A: true B: true C: true D: true
Decay Types and std::decay
in <type_traits>
Struct decay
:
template <class T> struct decay;
is used to obtain the decay type of T, which is aliased as member type decay::type
.
The decay type of T is the same type that results from the standard conversions that happen when an lvalue expression is used as an rvalue, with its cv-qualifier stripped. This resembles the implicit conversions happening when an argument is passed by value to a function.
Put more simply, if T is a reference type (say const int&
), then member value
is the type referred to by T with its const-ness removed (int
in this case).
Cases:
- If T is a function type, a function-to-pointer conversion is applied and the decay type is the same as:
add_pointer<T>::type
- If T is an array type, an array-to-pointer conversion is applied and the decay type is the same as:
add_pointer<remove_extent<remove_reference<T>::type>::type>::type
. (This very much resembles C decay) - Otherwise, a regular lvalue-to-rvalue conversion is applied and the decay type is the same as:
remove_cv<remove_reference<T>::type>::type
.
Notice that this class merely obtains a type using another type as model, but it does not transform values or objects between those types.
An example:
#include <type_traits> typedef std::decay<int>::type A; // int typedef std::decay<int&>::type B; // int typedef std::decay<int&&>::type C; // int typedef std::decay<const int&>::type D; // int typedef std::decay<int[2]>::type E; // int* typedef std::decay<int(int)>::type F; // int(*)(int) typedef int X[3];
These typedef's could be tested with:
#include <iostream> int main() { std::cout << std::boolalpha; std::cout << "typedefs of int:" << std::endl; std::cout << "A: " << std::is_same<int,A>::value << std::endl; std::cout << "B: " << std::is_same<int,B>::value << std::endl; std::cout << "C: " << std::is_same<int,C>::value << std::endl; std::cout << "D: " << std::is_same<int,D>::value << std::endl; std::cout << "E: " << std::is_same<int,E>::value << std::endl; std::cout << "F: " << std::is_same<int,F>::value << std::endl; return 0; }
Output:
typedefs of int: A: true B: true C: true D: true E: false F: false