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

Calling ranges::begin on a range returns an object
whose type models input_or_output_iterator ([iterator.concept.iterator]).

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_for<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 view concept specifies requirements on a range type
with constant-time destruction and move operations.

Common ranges are ranges for which
ranges::begin and ranges::end
return objects of the same type.

Random access ranges are ranges for which ranges::begin
returns a type that models
random_access_iterator ([iterator.concept.random.access]).

(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 =
requires(T& t) {
ranges::begin(t); // sometimes equality-preserving (see below)
ranges::end(t);
};
```

The required expressions
ranges::begin(t)
and
ranges::end(t)
of the range concept
do not require implicit expression variations ([concepts.equality]).

Given an expression t such that decltype((t)) is T&,
T models range only if

- [ranges::begin(t), ranges::end(t)) denotes a range ([iterator.requirements.general]),
- both ranges::begin(t) and ranges::end(t) are amortized constant time and non-modifying, and
- if the type of ranges::begin(t) models forward_iterator, ranges::begin(t) is equality-preserving.

[Note

: *end note*

]Equality preservation of both ranges::begin and
ranges::end enables passing a range whose iterator
type models forward_iterator 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 forward_iterator, 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.

β ```
template<class T>
concept borrowed_range =
range<T> &&
(is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
```

```
template<class>
inline constexpr bool enable_borrowed_range = false;
```

Remarks: Pursuant to [namespace.std], users may specialize enable_borrowed_range
for cv-unqualified program-defined types.

Such specializations shall be
usable in constant expressions ([expr.const]) and
have type const bool.

[Example

: *end example*

]Each specialization S of class template subrange ([range.subrange])
models borrowed_range because

β - enable_borrowed_range<S> is specialized to have the value true, and
- S's iterators do not have validity tied to the lifetime of an S object because they are βborrowedβ from some other range.

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

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

- ranges::size(t) is amortized , does not modify t, and is equal to ranges::distance(t), and
- if iterator_t<T> models forward_iterator,
ranges::size(t) is well-defined regardless of the evaluation of
ranges::begin(t). [Note: ranges::size(t) is otherwise not required to be well-defined after evaluating ranges::begin(t). For example, ranges::size(t) might be well-defined for a sized_range whose iterator type does not model forward_iterator only if evaluated before the first call to ranges::begin(t). β]
*end note*

```
template<class>
inline constexpr bool disable_sized_range = false;
```

Remarks: Pursuant to [namespace.std],
users may specialize disable_sized_range
for cv-unqualified program-defined types.

Such specializations shall
be usable in constant expressions ([expr.const]) and
have type const bool.

The view concept specifies the requirements of a range type
that has constant time move construction, move assignment, and destruction;
that is, the cost of these operations is
independent of the number of elements in the view.

```
template<class T>
concept view =
range<T> && movable<T> && default_initializable<T> && enable_view<T>;
```

[Example

: *end example*

]Examples of views are:

Most containers are not views since
destruction of the container destroys the elements,
which cannot be done in constant time.

β Since the difference between range and view is largely
semantic, the two are differentiated with the help of enable_view.

```
template<class T>
inline constexpr bool enable_view = derived_from<T, view_base>;
```

Remarks: Pursuant to [namespace.std], users may specialize enable_view
to true
for cv-unqualified program-defined types which model view,
and false for types which do not.

Such specializations shall
be usable in constant expressions ([expr.const]) and
have type const bool.

The output_range concept specifies requirements of a
range type for which ranges::begin returns
a model of output_iterator ([iterator.concept.output]).

input_range, forward_range, bidirectional_range,
and random_access_range are defined similarly.

```
template<class R, class T>
concept output_range =
range<R> && output_iterator<iterator_t<R>, T>;
template<class T>
concept input_range =
range<T> && input_iterator<iterator_t<T>>;
template<class T>
concept forward_range =
input_range<T> && forward_iterator<iterator_t<T>>;
template<class T>
concept bidirectional_range =
forward_range<T> && bidirectional_iterator<iterator_t<T>>;
template<class T>
concept random_access_range =
bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
```

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

```
template<class T>
concept contiguous_range =
random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
requires(T& t) {
{ ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>;
};
```

Given an expression t such that decltype((t)) is T&,
T models contiguous_range only if
to_address(ranges::begin(t)) == ranges::data(t)
is true.

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

[Example]

The viewable_range concept specifies the requirements of a
range type that can be converted to a view safely.