[range.access] (original) (raw)
25 Ranges library [ranges]
25.3.1 General [range.access.general]
In addition to being available via inclusion of the header, the customization point objects in [range.access] are available when the header 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.
25.3.2 ranges::begin [range.access.begin]
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 andenable_borrowed_range<remove_cv_t<T>> is false,ranges::begin(E) is ill-formed.
- Otherwise, if T is an array type ([dcl.array]) andremove_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 modelsinput_or_output_iterator,ranges::begin(E) is expression-equivalent toauto(t.begin()).
- Otherwise, if T is a class or enumeration type andauto(begin(t)) is a valid expression whose type modelsinput_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_]
25.3.3 ranges::end [range.access.end]
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 andenable_borrowed_range<remove_cv_t<T>> is false,ranges::end(E) is ill-formed.
- Otherwise, if T is an array type ([dcl.array]) andremove_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 tot + extent_v<T>.
- Otherwise, if auto(t.end()) is a valid expression whose type modelssentinel_for<iterator_t<T>> then ranges::end(E) is expression-equivalent toauto(t.end()).
- Otherwise, if T is a class or enumeration type andauto(end(t)) is a valid expression whose type modelssentinel_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 ofranges::end(E) and ranges::begin(E)model sentinel_for<S, I>.
— _end note_]
25.3.4 ranges::cbegin [range.access.cbegin]
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 andenable_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 toconst_iterator<decltype(U)>(U).
25.3.5 ranges::cend [range.access.cend]
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 andenable_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 toconst_sentinel<decltype(U)>(U).
[Note 1:
Whenever ranges::cend(E) is a valid expression, the types S and I of the expressionsranges::cend(E) and ranges::cbegin(E)model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— _end note_]
25.3.6 ranges::rbegin [range.access.rbegin]
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 andenable_borrowed_range<remove_cv_t<T>> is false,ranges::rbegin(E) is ill-formed.
- Otherwise, if T is an array type ([dcl.array]) andremove_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 modelsinput_or_output_iterator,ranges::rbegin(E) is expression-equivalent toauto(t.rbegin()).
- Otherwise, if T is a class or enumeration type andauto(rbegin(t)) is a valid expression whose type modelsinput_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 modelsbidirectional_iterator ([iterator.concept.bidir]),ranges::rbegin(E) is expression-equivalent tomake_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_]
25.3.7 ranges::rend [range.access.rend]
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 andenable_borrowed_range<remove_cv_t<T>> is false,ranges::rend(E) is ill-formed.
- Otherwise, if T is an array type ([dcl.array]) andremove_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 modelssentinel_for<decltype(ranges::rbegin(E))> then ranges::rend(E) is expression-equivalent toauto(t.rend()).
- Otherwise, if T is a class or enumeration type andauto(rend(t)) is a valid expression whose type modelssentinel_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 modelsbidirectional_iterator ([iterator.concept.bidir]), then ranges::rend(E) is expression-equivalent tomake_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 expressionsranges::rend(E) and ranges::rbegin(E)model sentinel_for<S, I>.
— _end note_]
25.3.8 ranges::crbegin [range.access.crbegin]
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 andenable_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 toconst_iterator<decltype(U)>(U).
25.3.9 ranges::crend [range.access.crend]
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 andenable_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 toconst_sentinel<decltype(U)>(U).
[Note 1:
Whenever ranges::crend(E) is a valid expression, the types S and I of the expressionsranges::crend(E) and ranges::crbegin(E)model sentinel_for<S, I>.
If S models input_iterator, then S also models constant-iterator.
— _end note_]
25.3.10 ranges::size [range.prim.size]
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 toauto(extent_v<T>).
- Otherwise, if disable_sized_range<remove_cv_t<T>> ([range.sized]) is false andauto(t.size()) is a valid expression of integer-like type ([iterator.concept.winc]),ranges::size(E) is expression-equivalent toauto(t.size()).
- Otherwise, if T is a class or enumeration type,disable_sized_range<remove_cv_t<T>> is false andauto(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, 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_]
25.3.11 ranges::ssize [range.prim.ssize]
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))>, orptrdiff_t if it is wider than that type;ranges::ssize(E) is expression-equivalent tostatic_cast<D>(ranges::size(t)).
25.3.12 ranges::reserve_hint [range.prim.size.hint]
Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E.
Then:
- If ranges::size(E) is a valid expression,ranges::reserve_hint(E) is expression-equivalent toranges::size(E).
- Otherwise, if auto(t.reserve_hint()) is a valid expression of integer-like type ([iterator.concept.winc]),ranges::reserve_hint(E) is expression-equivalent toauto(t.reserve_hint()).
- Otherwise, if T is a class or enumeration type andauto(reserve_hint(t)) is a valid expression of integer-like type where the meaning of reserve_hint is established as-if by performing argument-dependent lookup only ([basic.lookup.argdep]), thenranges::reserve_hint(E) is expression-equivalent to that expression.
- Otherwise,ranges::reserve_hint(E) is ill-formed.
[Note 1:
Diagnosable ill-formed cases above result in substitution failure whenranges::reserve_hint(E) appears in the immediate context of a template instantiation.
— _end note_]
[Note 2:
Whenever ranges::reserve_hint(E) is a valid expression, its type is integer-like.
— _end note_]
25.3.13 Approximately sized ranges [range.approximately.sized]
The approximately_sized_range concept refines rangewith the requirement that an approximation of the number of elements in the range can be determined in amortized constant time using ranges::reserve_hint.
template<class T> concept [approximately_sized_range](#concept:approximately%5Fsized%5Frange "25.3.13 Approximately sized ranges [range.approximately.sized]") = [range](range.range#concept:range "25.4.2 Ranges [range.range]")<T> && requires(T& t) { ranges::reserve_hint(t); };
Given an lvalue t of type remove_reference_t<T>,T models approximately_sized_range only if
- ranges::reserve_hint(t) is amortized , does not modify t, and has a value that is not negative and is representable in range_difference_t<T>, and
- if iterator_t<T> models forward_iterator,ranges::reserve_hint(t) is well-defined regardless of the evaluation of ranges::begin(t).
[Note 1:
ranges::reserve_hint(t) is otherwise not required to be well-defined after evaluating ranges::
begin(t).
For example, it is possible for ranges::reserve_hint(t) to be well-defined for an approximately_sized_range whose iterator type does not model forward_iteratoronly if evaluated before the first call to ranges::begin(t).
— _end note_]
25.3.14 ranges::empty [range.prim.empty]
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 tobool(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 tobool(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_]
25.3.15 ranges::data [range.prim.data]
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 andenable_borrowed_range<remove_cv_t<T>> is false,ranges::data(E) is ill-formed.
- Otherwise, if T is an array type ([dcl.array]) andremove_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 toauto(t.data()).
- Otherwise, if ranges::begin(t) is a valid expression whose type modelscontiguous_iterator,ranges::data(E) is expression-equivalent toto_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_]
25.3.16 ranges::cdata [range.prim.cdata]
template<class T> constexpr auto as-const-pointer(const T* p) noexcept { return p; }
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 andenable_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_]