25 Iterators library [iterators]

25.3 Iterator requirements [iterator.requirements]

25.3.4 Iterator concepts [iterator.concepts]

25.3.4.4 Concept weakly_­incrementable [iterator.concept.winc]

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.
[Note 1:
An integer-class type is not necessarily a class type.
— end note]
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.
In both cases, N is called the width of the 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:
The corresponding hypothetical specialization numeric_­limits<B(I)> meets the requirements on numeric_­limits specializations for integral types ([numeric.limits]).
— end note]
For every integral type J, let B(J) be the same type as J.
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++ and a-- shall be prvalues of type I whose values are equal to that of a prior to the evaluation of the expressions.
    The expression a++ shall modify the value of a by adding 1 to it.
    The expression a-- shall modify the value of a by subtracting 1 from it.
  • 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.
    If @x has type bool, so too does @a; if @x has type B(I), then @a has type I.
  • For every assignment operator @= for which c @= x is well-formed, c @= a shall also be well-formed and shall have the same value and effects as c @= x.
    The expression c @= a shall be an lvalue referring to c.
  • For every assignment operator @= for which x @= y is well-formed, a @= b shall also be well-formed and shall have the same effects as x @= y, except that the value that would be stored into x is stored into a.
    The expression a @= b shall be an lvalue referring to a.
  • 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]).
A value-initialized object of integer-class type has value 0.
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.
is-integer-like<I> is true if and only if I is an integer-like type.
is-signed-integer-like<I> is true if and only if I is a signed-integer-like type.
Let i be an object of type I.
When i is in the domain of both pre- and post-increment, i is said to be incrementable.
I models weakly_­incrementable<I> only if
  • The expressions ++i and i++ have the same domain.
  • If i is incrementable, then both ++i and i++ advance i to the next element.
  • If i is incrementable, then addressof(++i) is equal to addressof(i).
Recommended practice: The implementaton of an algorithm on a weakly incrementable type should never attempt to pass through the same incrementable value twice; such an algorithm should be a single-pass algorithm.
[Note 3:
For weakly_­incrementable types, a equals b does not imply that ++a equals ++b.
(Equality does not guarantee the substitution property or referential transparency.)
Such algorithms can be used with istreams as the source of the input data through the istream_­iterator class template.
— end note]