The weakly_incrementable concept specifies the requirements on
types that can be incremented with the pre- and post-increment operators.

The increment operations are not required to be equality-preserving,
nor is the type required to be equality_comparable.

template<class T>
inline constexpr bool *is-integer-like* = *see below*; // *exposition only*
template<class T>
inline constexpr bool *is-signed-integer-like* = *see below*; // *exposition only*
template<class I>
concept weakly_incrementable =
movable<I> &&
requires(I i) {
typename iter_difference_t<I>;
requires *is-signed-integer-like*<iter_difference_t<I>>;
{ ++i } -> same_as<I&>; // not required to be equality-preserving
i++; // not required to be equality-preserving
};

A type I is an *integer-class type*
if it is in a set of implementation-defined types
that behave as integer types do, as defined below.

The range of representable values of an integer-class type
is the continuous set of values over which it is defined.

For any integer-class type,
its range of representable values is
either to (inclusive) for some integer N,
in which case it is a *signed-integer-class type*, or
0 to (inclusive) for some integer N,
in which case it is an *unsigned-integer-class type*.

The width of an integer-class type is greater than
that of every integral type of the same signedness.

A type I other than cv bool is *integer-like*
if it models integral<I> or
if it is an integer-class type.

An integer-like type I is *signed-integer-like*
if it models signed_integral<I> or
if it is a signed-integer-class type.

An integer-like type I is *unsigned-integer-like*
if it models unsigned_integral<I> or
if it is an unsigned-integer-class type.

For every integer-class type I,
let B(I) be a unique hypothetical extended integer type
of the same signedness with the same width ([basic.fundamental]) as I.

[*Note 2*: *end note*]

The corresponding hypothetical specialization numeric_limits<B(I)>
meets the requirements on numeric_limits specializations
for integral types ([numeric.limits]).

— 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 ,
where N is the width of the destination type.

Let a be an object of integer-class type I,
let b be an object of integer-like type I2
such that the expression b is implicitly convertible to I,
let x and y be, respectively,
objects of type B(I) and B(I2) as described above
that represent the same values as a and b, and
let c be an lvalue of any integral type.

- The expressions ++a, --a, and &a shall be expression-equivalent to a += 1, a -= 1, and addressof(a), respectively.
- For every
*unary-operator*@ other than & for which the expression @x is well-formed, @a shall also be well-formed and have the same value, effects, and value category as @x. - For every non-assignment binary operator @ for which x @ y and y @ x are well-formed, a @ b and b @ a shall also be well-formed and shall have the same value, effects, and value category as x @ y and y @ x, respectively.If x @ y or y @ x has type B(I), then a @ b or b @ a, respectively, has type I; if x @ y or y @ x has type B(I2), then a @ b or b @ a, respectively, has type I2; if x @ y or y @ x has any other type, then a @ b or b @ a, respectively, has that type.

An expression E of integer-class type I is
contextually convertible to bool
as if by bool(E != I(0)).

All integer-class types model
regular ([concepts.object]) and
three_way_comparable<strong_ordering> ([cmp.concept]).

For every (possibly cv-qualified) integer-class type I,
numeric_limits<I> is specialized such that
each static data member m
has the same value as numeric_limits<B(I)>::m, and
each static member function f
returns I(numeric_limits<B(I)>::f()).

For any two integer-like types I1 and I2,
at least one of which is an integer-class type,
common_type_t<I1, I2> denotes an integer-class type
whose width is not less than that of I1 or I2.

If both I1 and I2 are signed-integer-like types,
then common_type_t<I1, I2> is also a signed-integer-like type.