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 =
default_initializable<I> && 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 class types
that behave as integer types do, as defined in below.

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

The values 0 and 1 are part of the range of every integer-class type.

If any negative numbers are part of the range,
the type is a *signed-integer-class type*;
otherwise, it is an *unsigned-integer-class type*.

For every integer-class type I,
let B(I) be a hypothetical extended integer type
of the same signedness with the smallest width ([basic.fundamental])
capable of representing the same range of values.

Let a and b be objects of integer-class type I,
let x and y be objects of type B(I) as described above
that represent the same values as a and b respectively, and
let c be an lvalue of any integral 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
totally_ordered ([concept.totallyordered]).

For every (possibly cv-qualified) integer-class type I,
numeric_limits<I> is specialized such that:

- numeric_limits<I>::is_specialized is true,
- numeric_limits<I>::is_signed is true if and only if I is a signed-integer-class type,
- numeric_limits<I>::is_integer is true,
- numeric_limits<I>::is_exact is true,
- numeric_limits<I>::digits is equal to the width of the integer-class type,
- numeric_limits<I>::digits10 is equal to static_cast<int>(digits * log10(2)), and
- numeric_limits<I>::min() and numeric_limits<I>::max() return the lowest and highest representable values of I, respectively, and numeric_limits<I>::lowest() returns numeric_limits<I>::min().

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

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