In addition to being available via inclusion of the <experimental/ranges/range> header, the customization point objects in [range.primitives] are available when <experimental/ranges/iterator> is included.
The name size denotes a customization point object ([customization.point.object]). The expression ranges::size(E) for some subexpression E with type T is expression-equivalent to:
DECAY_COPY(extent<T>::value) if T is an array type ( ISO/IEC 14882:2014 §[basic.compound]).
Otherwise, DECAY_COPY(static_cast<const T&>(E).size()) if it is a valid expression and its type I satisfies Integral<I> and disable_sized_range<T> ([ranges.sized]) is false.
Otherwise, DECAY_COPY(size(static_cast<const T&>(E))) if it is a valid expression and its type I satisfies Integral<I> with overload resolution performed in a context that includes the declaration void size(const auto&) = delete; and does not include a declaration of ranges::size, and disable_sized_range<T> is false.
Otherwise, DECAY_COPY(ranges::cend(E) - ranges::cbegin(E)), except that E is only evaluated once, if it is a valid expression and the types I and S of ranges::cbegin(E) and ranges::cend(E) meet the syntactic requirements of SizedSentinel<S, I> ([iterators.sizedsentinel]) and ForwardIterator<I>. If SizedSentinel and ForwardIterator are not satisfied, the program is ill-formed with no diagnostic required.
Otherwise, ranges::size(E) is ill-formed.
[ Note: Whenever ranges::size(E) is a valid expression, its type satisfies Integral. — end note ]
The name empty denotes a customization point object ([customization.point.object]). 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, bool(ranges::begin(E) == ranges::end(E)), except that E is only evaluated once, if it is a valid expression and the type of ranges::begin(E) satisfies ForwardIterator.
Otherwise, ranges::empty(E) is ill-formed.
[ Note: Whenever ranges::empty(E) is a valid expression, it has type bool. — end note ]
The name data denotes a customization point object ([customization.point.object]). The expression ranges::data(E) for some subexpression E is expression-equivalent to:
ranges::data(static_cast<const T&>(E)) if E is an rvalue of type T. This usage is deprecated. [ Note: This deprecated usage exists so that ranges::data(E) behaves similarly to std::data(E) as defined in the C++ Working Paper when E is an rvalue. — end note ]
Otherwise, DECAY_COPY((E).data()) if it is a valid expression of pointer to object type.
Otherwise, ranges::begin(E) if it is a valid expression of pointer to object type.
Otherwise, ranges::data(E) is ill-formed.
[ Note: Whenever ranges::data(E) is a valid expression, it has pointer to object type. — end note ]
The name cdata denotes a customization point object ([customization.point.object]). The expression ranges::cdata(E) for some subexpression E of type T is expression-equivalent to ranges::data(static_cast<const T&>(E)).
Use of ranges::cdata(E) with rvalue E is deprecated. [ Note: This deprecated usage exists so that ranges::cdata(E) has behavior consistent with ranges::data(E) when E is an rvalue. — end note ]
[ Note: Whenever ranges::cdata(E) is a valid expression, it has pointer to object type. — end note ]