26 Ranges library [ranges]

26.3 Range access [range.access]

26.3.1 General [range.access.general]

In addition to being available via inclusion of the <ranges> header, the customization point objects in [range.access] are available when <iterator> is included.
Within [range.access], the reified object of a subexpression E denotes
  • the same object as E if E is a glvalue, or
  • the result of applying the temporary materialization conversion ([conv.rval]) to E otherwise.

26.3.2 ranges​::​begin [range.access.begin]

The name ranges​::​begin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​begin(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​begin(E) is ill-formed with no diagnostic required.
  • Otherwise, if T is an array type, ranges​::​begin(E) is expression-equivalent to t + 0.
  • Otherwise, if auto(t.begin()) is a valid expression whose type models input_or_output_iterator, ranges​::​begin(E) is expression-equivalent to auto(t.begin()).
  • Otherwise, if T is a class or enumeration type and auto(begin(t)) is a valid expression whose type models input_or_output_iterator where the meaning of begin is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​begin(E) is expression-equivalent to that expression.
  • Otherwise, ranges​::​begin(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​begin(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​begin(E) is a valid expression, its type models input_or_output_iterator.
— end note]

26.3.3 ranges​::​end [range.access.end]

The name ranges​::​end denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​end(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​end(E) is ill-formed with no diagnostic required.
  • Otherwise, if T is an array of unknown bound, ranges​::​end(E) is ill-formed.
  • Otherwise, if T is an array, ranges​::​end(E) is expression-equivalent to t + extent_v<T>.
  • Otherwise, if auto(t.end()) is a valid expression whose type models sentinel_for<iterator_t<T>> then ranges​::​end(E) is expression-equivalent to auto(t.end()).
  • Otherwise, if T is a class or enumeration type and auto(end(t)) is a valid expression whose type models sentinel_for<iterator_t<T>> where the meaning of end is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​end(E) is expression-equivalent to that expression.
  • Otherwise, ranges​::​end(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​end(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​end(E) is a valid expression, the types S and I of ranges​::​end(E) and ranges​::​begin(E) model sentinel_for<S, I>.
— end note]

26.3.4 ranges​::​cbegin [range.access.cbegin]

The name ranges​::​cbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cbegin(E) is ill-formed.
  • Otherwise, let U be ranges​::​begin(possibly-const-range(t)).
    ranges​::​cbegin(E) is expression-equivalent to const_iterator<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​cbegin(E) is a valid expression, its type models input_or_output_iterator and constant-iterator.
— end note]

26.3.5 ranges​::​cend [range.access.cend]

The name ranges​::​cend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cend(E) is ill-formed.
  • Otherwise, let U be ranges​::​end(possibly-const-range(t)).
    ranges​::​cend(E) is expression-equivalent to const_sentinel<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​cend(E) is a valid expression, the types S and I of the expressions ranges​::​cend(E) and ranges​::​cbegin(E) model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— end note]

26.3.6 ranges​::​rbegin [range.access.rbegin]

The name ranges​::​rbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​rbegin(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​rbegin(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.rbegin()) is a valid expression whose type models input_or_output_iterator, ranges​::​rbegin(E) is expression-equivalent to auto(t.rbegin()).
  • Otherwise, if T is a class or enumeration type and auto(rbegin(t)) is a valid expression whose type models input_or_output_iterator where the meaning of rbegin is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​rbegin(E) is expression-equivalent to that expression.
  • Otherwise, if both ranges​::​begin(t) and ranges​::​end(t) are valid expressions of the same type which models bidirectional_iterator ([iterator.concept.bidir]), ranges​::​rbegin(E) is expression-equivalent to make_reverse_iterator(ranges​::​end(t)).
  • Otherwise, ranges​::​rbegin(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​rbegin(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​rbegin(E) is a valid expression, its type models input_or_output_iterator.
— end note]

26.3.7 ranges​::​rend [range.access.rend]

The name ranges​::​rend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​rend(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​rend(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.rend()) is a valid expression whose type models sentinel_for<decltype(​ranges​::​rbegin(E))> then ranges​::​rend(E) is expression-equivalent to auto(t.rend()).
  • Otherwise, if T is a class or enumeration type and auto(rend(t)) is a valid expression whose type models sentinel_for<decltype(ranges​::​rbegin(E))> where the meaning of rend is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​rend(E) is expression-equivalent to that expression.
  • Otherwise, if both ranges​::​begin(t) and ranges​::​end(t) are valid expressions of the same type which models bidirectional_iterator ([iterator.concept.bidir]), then ranges​::​rend(E) is expression-equivalent to make_reverse_iterator(ranges​::​begin(t)).
  • Otherwise, ranges​::​rend(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​rend(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​rend(E) is a valid expression, the types S and I of the expressions ranges​::​rend(E) and ranges​::​rbegin(E) model sentinel_for<S, I>.
— end note]

26.3.8 ranges​::​crbegin [range.access.crbegin]

The name ranges​::​crbegin denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​crbegin(E) is ill-formed.
  • Otherwise, let U be ranges​::​rbegin(possibly-const-range(t)).
    ranges​::​crbegin(E) is expression-equivalent to const_iterator<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​crbegin(E) is a valid expression, its type models input_or_output_iterator and constant-iterator.
— end note]

26.3.9 ranges​::​crend [range.access.crend]

The name ranges​::​crend denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​crend(E) is ill-formed.
  • Otherwise, let U be ranges​::​rend(possibly-const-range(t)).
    ranges​::​crend(E) is expression-equivalent to const_sentinel<decltype(U)>(U).
[Note 1: 
Whenever ranges​::​crend(E) is a valid expression, the types S and I of the expressions ranges​::​crend(E) and ranges​::​crbegin(E) model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— end note]

26.3.10 ranges​::​size [range.prim.size]

The name ranges​::​size denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If T is an array of unknown bound ([dcl.array]), ranges​::​size(E) is ill-formed.
  • Otherwise, if T is an array type, ranges​::​size(E) is expression-equivalent to auto(extent_v<T>).
  • Otherwise, if disable_sized_range<remove_cv_t<T>> ([range.sized]) is false and auto(t.size()) is a valid expression of integer-like type ([iterator.concept.winc]), ranges​::​size(E) is expression-equivalent to auto(​t.size()).
  • Otherwise, if T is a class or enumeration type, disable_sized_range<remove_cv_t<T>> is false and auto(size(t)) is a valid expression of integer-like type where the meaning of size is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), then ranges​::​size(E) is expression-equivalent to that expression.
  • Otherwise, if to-unsigned-like(ranges​::​end(t) - ranges​::​begin(t)) ([ranges.syn]) is a valid expression and the types I and S of ranges​::​begin(t) and ranges​::​end(t) (respectively) model both sized_sentinel_for<S, I> ([iterator.concept.sizedsentinel]) and forward_iterator<I>, then ranges​::​size(E) is expression-equivalent to to-unsigned-like(ranges​::​end(t) - ranges​::​begin(t)).
  • Otherwise, ranges​::​size(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​size(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​size(E) is a valid expression, its type is integer-like.
— end note]

26.3.11 ranges​::​ssize [range.prim.ssize]

The name ranges​::​ssize denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
If ranges​::​size(t) is ill-formed, ranges​::​ssize(E) is ill-formed.
Otherwise let D be make-signed-like-t<decltype(ranges​::​​size(t))>, or ptrdiff_t if it is wider than that type; ranges​::​ssize(E) is expression-equivalent to static_cast<D>(ranges​::​size(t)).

26.3.12 ranges​::​empty [range.prim.empty]

The name ranges​::​empty denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If T is an array of unknown bound ([dcl.array]), ranges​::​empty(E) is ill-formed.
  • Otherwise, if bool(t.empty()) is a valid expression, ranges​::​empty(E) is expression-equivalent to bool(t.empty()).
  • Otherwise, if (ranges​::​size(t) == 0) is a valid expression, ranges​::​empty(E) is expression-equivalent to (ranges​::​size(t) == 0).
  • Otherwise, if bool(ranges​::​begin(t) == ranges​::​end(t)) is a valid expression and the type of ranges​::​begin(t) models forward_iterator, ranges​::​empty(E) is expression-equivalent to bool(​ranges​::​begin(t) == ranges​::​end(t)).
  • Otherwise, ranges​::​empty(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​empty(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​empty(E) is a valid expression, it has type bool.
— end note]

26.3.13 ranges​::​data [range.prim.data]

The name ranges​::​data denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​data(E) is ill-formed.
  • Otherwise, if T is an array type ([dcl.array]) and remove_all_extents_t<T> is an incomplete type, ranges​::​data(E) is ill-formed with no diagnostic required.
  • Otherwise, if auto(t.data()) is a valid expression of pointer to object type, ranges​::​data(E) is expression-equivalent to auto(t.data()).
  • Otherwise, if ranges​::​begin(t) is a valid expression whose type models contiguous_iterator, ranges​::​data(E) is expression-equivalent to to_address(ranges​::​begin(t)).
  • Otherwise, ranges​::​data(E) is ill-formed.
[Note 1: 
Diagnosable ill-formed cases above result in substitution failure when ranges​::​data(E) appears in the immediate context of a template instantiation.
— end note]
[Note 2: 
Whenever ranges​::​data(E) is a valid expression, it has pointer to object type.
— end note]

26.3.14 ranges​::​cdata [range.prim.cdata]

template<class T> constexpr auto as-const-pointer(const T* p) { return p; } // exposition only
The name ranges​::​cdata denotes a customization point object ([customization.point.object]).
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
  • If E is an rvalue and enable_borrowed_range<remove_cv_t<T>> is false, ranges​::​cdata(E) is ill-formed.
  • Otherwise, ranges​::​cdata(E) is expression-equivalent to as-const-pointer(ranges​::​data(possibly-const-range(t))).
[Note 1: 
Whenever ranges​::​cdata(E) is a valid expression, it has pointer to constant object type.
— end note]