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.

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 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 1*: *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.

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

Given an expression E such that decltype((E)) is T,
T models borrowed_range only if
the validity of iterators obtained from the object denoted by E
is not tied to the lifetime of that object.

[*Note 2*: *end note*]

Since the validity of iterators is not tied to the lifetime of
an object whose type models borrowed_range,
a function can accept arguments of such a type by value and
return iterators obtained from it without danger of dangling.

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

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

[*Example 1*: *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.

```
template<class T>
concept sized_range =
range<T> &&
requires(T& t) { ranges::size(t); };
```

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 1*: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;
```

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

[*Note 2*: *end note*]

disable_sized_range allows use of range types with the library
that satisfy but do not in fact model sized_range.

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

[*Example 1*:

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

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

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.

```
template<class T>
concept common_range =
range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
```

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

```
template<class T>
concept viewable_range =
range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
```