In addition to being available via inclusion of the <ranges>
header, the customization point objects in [range.access] are
available when <iterator> is included.

The expression
ranges::begin(E) for some subexpression E is
expression-equivalent to:

- E + 0 if E is an lvalue of array type ([basic.compound]).
- Otherwise, if E is an lvalue, decay-copy(E.begin()) if it is a valid expression and its type I models input_or_output_iterator.
- Otherwise, decay-copy(begin(E)) if it is a
valid expression and its type I models
input_or_output_iterator with overload
resolution performed in a context that includes the declarations:
template<class T> void begin(T&&) = delete; template<class T> void begin(initializer_list<T>&&) = delete;

and does not include a declaration of ranges::begin. - Otherwise, ranges::begin(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::begin(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::end(E) for some subexpression E is
expression-equivalent to:

- E + extent_v<T> if E is an lvalue of array type ([basic.compound]) T.
- Otherwise, if E is an lvalue,
decay-copy(E.end())
if it is a valid expression and its type S models
sentinel_for<decltype(ranges::begin(E))>

- Otherwise, decay-copy(end(E)) if it is a valid
expression and its type S models
sentinel_for<decltype(ranges::begin(E))>

with overload resolution performed in a context that includes the declarations:template<class T> void end(T&&) = delete; template<class T> void end(initializer_list<T>&&) = delete;

and does not include a declaration of ranges::end. - Otherwise, ranges::end(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::end(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::rbegin(E) for some subexpression E is
expression-equivalent to:

- If E is an lvalue, decay-copy(E.rbegin()) if it is a valid expression and its type I models input_or_output_iterator.
- Otherwise, decay-copy(rbegin(E)) if it is a valid
expression and its type I models
input_or_output_iterator with overload
resolution performed in a context that includes the declaration:
template<class T> void rbegin(T&&) = delete;

and does not include a declaration of ranges::rbegin. - Otherwise, make_reverse_iterator(ranges::end(E)) if both ranges::begin(E) and ranges::end(E) are valid expressions of the same type I which models bidirectional_iterator ([iterator.concept.bidir]).
- Otherwise, ranges::rbegin(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::rbegin(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::rend(E) for some subexpression E is
expression-equivalent to:

- If E is an lvalue, decay-copy(E.rend())
if it is a valid expression and its type S models
sentinel_for<decltype(ranges::rbegin(E))>

- Otherwise, decay-copy(rend(E)) if it is a valid
expression and its type S models
sentinel_for<decltype(ranges::rbegin(E))>

with overload resolution performed in a context that includes the declaration:template<class T> void rend(T&&) = delete;

and does not include a declaration of ranges::rend. - Otherwise, make_reverse_iterator(ranges::begin(E)) if both ranges::begin(E) and ranges::end(E) are valid expressions of the same type I which models bidirectional_iterator ([iterator.concept.bidir]).
- Otherwise, ranges::rend(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::rend(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::size(E) for some subexpression E with type
T is expression-equivalent to:

- decay-copy(extent_v<T>) if T is an array type ([basic.compound]).
- Otherwise, if
disable_sized_range<remove_cv_t<T>> ([range.sized])
is false:
- decay-copy(E.size()) if it is a valid expression and its type I is integer-like ([iterator.concept.winc]).
- Otherwise, decay-copy(size(E))
if it is a valid expression and its type I
is integer-like
with overload resolution performed in a context that includes
the declaration:
template<class T> void size(T&&) = delete;

and does not include a declaration of ranges::size.

- Otherwise, make-unsigned-like(ranges::end(E) - ranges::begin(E)) ([range.subrange]) if it is a valid expression and the types I and S of ranges::begin(E) and ranges::end(E) (respectively) model both sized_sentinel_for<S, I> ([iterator.concept.sizedsentinel]) and forward_iterator<I>. However, E is evaluated only once.
- Otherwise, ranges::size(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::size(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::empty(E) for some subexpression E is
expression-equivalent to:

- bool((E).empty()) if it is a valid expression.
- Otherwise, (ranges::size(E) == 0) if it is a valid expression.
- Otherwise, EQ, where EQ is bool(ranges::begin(E) == ranges::end(E)) except that E is only evaluated once, if EQ is a valid expression and the type of ranges::begin(E) models forward_iterator.
- Otherwise, ranges::empty(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::empty(E) appears in the immediate context of a template instantiation. —]
*end note*

The expression
ranges::data(E) for some subexpression E is
expression-equivalent to:

- If E is an lvalue, decay-copy(E.data()) if it is a valid expression of pointer to object type.
- Otherwise, if ranges::begin(E) is a valid expression whose type models contiguous_iterator, to_address(ranges::begin(E)).
- Otherwise, ranges::data(E) is ill-formed. [ Note: This case can result in substitution failure when ranges::data(E) appears in the immediate context of a template instantiation. —]
*end note*