23 Ranges library [ranges]

23.4 Range primitives [range.prim]

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

23.4.1 size [range.prim.size]

The name size denotes a customization point object.
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 models Integral.
    • Otherwise, decay-copy(size(E)) if it is a valid expression and its type I models Integral 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, (ranges::end(E) - ranges::begin(E)) if it is a valid expression and the types I and S of ranges::begin(E) and ranges::end(E) model SizedSentinel<S, I> ([iterator.concept.sizedsentinel]) and ForwardIterator<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
    ]
[Note
:
Whenever ranges::size(E) is a valid expression, its type models Integral.
end note
]

23.4.2 empty [range.prim.empty]

The name empty denotes a 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, 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 ForwardIterator.
  • 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
    ]
[Note
:
Whenever ranges::empty(E) is a valid expression, it has type bool.
end note
]

23.4.3 data [range.prim.data]

The name data denotes a customization point object.
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 ContiguousIterator,
      ranges::begin(E) == ranges::end(E) ? nullptr : addressof(*ranges::begin(E))
      
    except that E is evaluated only once.
  • 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
    ]
[Note
:
Whenever ranges::data(E) is a valid expression, it has pointer to object type.
end note
]

23.4.4 cdata [range.prim.cdata]

The name cdata denotes a 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)) if E is an lvalue.
  • Otherwise, ranges::data(static_­cast<const T&&>(E)).
[Note
:
Whenever ranges::cdata(E) is a valid expression, it has pointer to object type.
end note
]