is-integer-like , is-signed-integer-like
template< class T > constexpr bool /*is-integer-like*/ = /* see description */; |
(1) | (since C++20) (exposition only*) |
template< class T > constexpr bool /*is-signed-integer-like*/ = /* see description */; |
(2) | (since C++20) (exposition only*) |
/*is-integer-like*/<T> is true if and only if T is an integer-like type./*is-signed-integer-like*/<T> is true if and only if T is a signed-integer-like type.Integer-class type
A type T is an integer-class type if it is in a set of implementation-defined types that behave as integer types do, as defined below. An integer-class type is not necessarily a class type.
An integer-class type can represent 2N
consecutive integers, where N, a positive integer, is called the width of the integer-class type.
An integer-class type is either signed or unsigned:
- A signed integer class type can represent all integers in
[-2N-1,2N-1
-1], whereNis greater than the width of every signed integral type. - An unsigned integer class type can represent all integers in
[0,2N
-1], whereNis greater than the width of every unsigned integral type.
All integer-class types model regular and three_way_comparable<std::strong_ordering>.
A value-initialized object of integer-class type has value 0.
An expression E of integer-class type T is contextually convertible to bool as if by bool(E != T(0)).
Integer-like type
A type other than (possibly cv-qualified) bool is integer-like if it models integral or if it is an integer-class type.
- An integer-like type is signed-integer-like if it models
signed_integralor if it is a signed-integer-class type. - An integer-like type is unsigned-integer-like if it models
unsigned_integralor if it is an unsigned-integer-class type.
Required behaviors
Expressions of integer-class type are explicitly convertible to any integer-like type, and implicitly convertible to any integer-class type of equal or greater width and the same signedness. Expressions of integral type are both implicitly and explicitly convertible to any integer-class type. Conversions between integral and integer-class types and between two integer-class types do not exit via an exception. The result of such a conversion is the unique value of the destination type that is congruent to the source modulo 2N
, where N is the width of the destination type.
Let Int<T> denote the following type:
- If
Tis an integer-class type,Int<T>is a unique hypothetical extended integer type of the same signedness with the same width asT. - If
Tis an integral type, letInt<T>is the same type asT.
Given the following types, values and operators:
| Type | Definition |
IC
|
an integer-class type |
IL
|
an integer-like type |
| Value | Definition |
a
|
an object of type IC
|
b
|
an object of type IL
|
c
|
an lvalue of an integeral type |
x
|
an object of type Int<IC> that represent the same value as a
|
y
|
an object of type Int<IL> that represent the same value as b
|
| Operator | Definition |
@=
|
one of +=, -=, *=, /=, %=, &=, |=, ^=, <<= and >>=
|
@
|
one of +, -, *, /, %, &, |, ^, <<, >>, &&, ||, ==, !=, <, >, <=, >=, <=> and ,
|
The following expressions must be well-formed and have their specified result and effects if the specified conditions are satisfied:
| Expression | Condition | Result | Effects |
|---|---|---|---|
a++
|
No condition | a prvalue of type IC whose value is equal to that of a prior to the evaluation
|
modifies the value of a by adding 1 to it
|
a--
|
modifies the value of a by subtracting 1 to it
| ||
++a
|
expression-equivalent to a += 1
| ||
--a
|
expression-equivalent to a -= 1
| ||
&a
|
expression-equivalent to std::addressof(a)
| ||
!a
|
!x is well-formed
|
same as !x
| |
+a
|
+x is well-formed
|
same as +x, but has type IC
|
same as +x
|
-a
|
-x is well-formed
|
same as -x, but has type IC
|
same as -x
|
~a
|
~x is well-formed
|
same as ~x, but has type IC
|
same as ~x
|
c @= a
|
c @= x is well-formed
|
an lvalue referring to c
|
same as c @= x
|
a @= b
|
x @= y is well-formed
|
an lvalue referring to a
|
same as x @= y, except that the value that would be stored into x is stored into a
|
a @ b
|
x @ y is well-formed
|
same as x @ y, but the result type is different:
|
same as x @ y
|
b @ a
|
y @ x is well-formed
|
same as y @ x, but the result type is different:
|
same as y @ x
|
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3366 (P2393R1) |
C++20 | the conversion between an integer-class type and its corresponding integer type was not guaranteed to produce a representable value |
guaranteed |
| LWG 3376 (P2393R1) |
C++20 | integer-class types could only be class types | also allowed non-class types |
| LWG 3467 | C++20 | bool was considered as an integer-like type
|
excluded |
| LWG 3575 (P2393R1) |
C++20 | integer-class types were not guaranteed to be three-way-comparable | guaranteed |
See also
(C++20) |
specifies that a semiregular type can be incremented with pre- and post-increment operators (concept) |