Ranges are an abstraction that allow a C++ program
to operate on elements of data structures uniformly.

Calling ranges::end on a range returns an object whose type S,
together with the type I of the object returned by ranges::begin,
models Sentinel<S, I>.

The library formalizes the interfaces, semantics, and complexity of ranges
to enable algorithms and range adaptors that work efficiently
on different types of sequences.

The Range concept requires that
ranges::begin and ranges::end
return an iterator and a sentinel, respectively.

The SizedRange concept refines Range with
the requirement that the number of elements in the range can be determined
in constant time using the ranges::size function.

The View concept specifies requirements on a Range type
with constant-time copy and assign operations.

Several refinements of Range group requirements
that arise frequently in concepts and algorithms.

Random access ranges are ranges for which ranges::begin
returns a type that models
RandomAccessIterator.

(Contiguous, bidirectional, forward, input, and output ranges
are defined similarly.)

Viewable ranges can be converted to views.

The Range concept defines the requirements of a type that allows
iteration over its elements by providing an iterator and sentinel
that denote the elements of the range.

```
template<class T>
concept range-impl = // exposition only
requires(T&& t) {
ranges::begin(std::forward<T>(t)); // sometimes equality-preserving (see below)
ranges::end(std::forward<T>(t));
};
template<class T>
concept Range = range-impl<T&>;
template<class T>
concept forwarding-range = // exposition only
Range<T> && range-impl<T>;
```

The required expressions
ranges::begin(std::forward<T>(t))
and
ranges::end(std::forward<T>(t))
of the range-impl concept
do not require implicit expression variations ([concepts.equality]).

Given an expression E such that decltype((E)) is T,
T models range-impl only if

- both ranges::begin(E) and ranges::end(E) are amortized constant time and non-modifying, and

[βNote

: *end note*

β]Equality preservation of both ranges::begin and
ranges::end enables passing a Range whose iterator
type models ForwardIterator to multiple
algorithms and making multiple passes over the range by repeated calls to
ranges::begin and ranges::end.

Since ranges::begin is not required to be equality-preserving
when the return type does not model ForwardIterator, repeated calls
might not return equal values or might not be well-defined;
ranges::begin should be called at most once for such a range.

ββGiven an expression E such that decltype((E)) is T
and an lvalue t that denotes the same object as E,
T models forwarding-range only if

- ranges::begin(E) and ranges::begin(t) are expression-equivalent,
- ranges::end(E) and ranges::end(t) are expression-equivalent, and
- the validity of iterators obtained from the object denoted by E is not tied to the lifetime of that object.

The SizedRange concept specifies the requirements
of a Range type that knows its size in constant time with the
size function.

```
template<class T>
concept SizedRange =
Range<T> &&
!disable_sized_range<remove_cvref_t<T>> &&
requires(T& t) { ranges::size(t); };
```

Given an lvalue t of type remove_reference_t<T>, T
models SizedRange only if

- ranges::size(t) is , does not modify t, and is equal to ranges::distance(t), and
- if iterator_t<T> models ForwardIterator, ranges::size(t) is well-defined regardless of the evaluation of ranges::begin(t).

The View concept specifies the requirements of a Range type
that has constant time copy, move, and assignment operators; that is, the cost of
these operations is not proportional to the number of elements in the
View.

[βExample

: *end example*

β]Examples of Views are:

Most containers are not views since
copying the container copies the elements,
which cannot be done in constant time.

ββ```
template<class T>
inline constexpr bool enable_view = see below;
template<class T>
concept View =
Range<T> && Semiregular<T> && enable_view<T>;
```

For a type T, the default value of enable_view<T> is:

- Otherwise, if T is a specialization of class template initializer_list, set, multiset, unordered_set, unordered_multiset, or match_results, false.
- Otherwise, if both T and const T model Range and iter_reference_t<iterator_t<T>> is not the same type as iter_reference_t<iterator_t<const T>>, false.
- Otherwise, true.

Pursuant to [namespace.std], users may specialize enable_view
to true for types which model View,
and false for types which do not.

The OutputRange concept specifies requirements of a
Range type for which ranges::begin returns
a model of OutputIterator.

```
template<class R, class T>
concept OutputRange =
Range<R> && OutputIterator<iterator_t<R>, T>;
template<class T>
concept InputRange =
Range<T> && InputIterator<iterator_t<T>>;
template<class T>
concept ForwardRange =
InputRange<T> && ForwardIterator<iterator_t<T>>;
template<class T>
concept BidirectionalRange =
ForwardRange<T> && BidirectionalIterator<iterator_t<T>>;
template<class T>
concept RandomAccessRange =
BidirectionalRange<T> && RandomAccessIterator<iterator_t<T>>;
```

ContiguousRange additionally requires that
the ranges::data customization point ([range.prim.data])
is usable with the range.

```
template<class T>
concept ContiguousRange =
RandomAccessRange<T> && ContiguousIterator<iterator_t<T>> &&
requires(T& t) {
{ ranges::data(t) } -> Same<add_pointer_t<iter_reference_t<iterator_t<T>>>>;
};
```

The CommonRange concept specifies requirements of
a Range type for which ranges::begin and
ranges::end return objects of the same type.

```
template<class T>
concept CommonRange =
Range<T> && Same<iterator_t<T>, sentinel_t<T>>;
```

The ViewableRange concept specifies the requirements of a
Range type that can be converted to a View safely.

```
template<class T>
concept ViewableRange =
Range<T> && (forwarding-range<T> || View<decay_t<T>>);
```