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 sized_range 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.

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-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

- [ranges::begin(E), ranges::end(E)) denotes a range ([iterator.requirements.general]),
- both ranges::begin(E) and ranges::end(E) are amortized constant time and non-modifying, and
- if the type of ranges::begin(E) models forward_iterator, ranges::begin(E) 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.

β 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 sized_range concept specifies the requirements
of a range type that knows its size in constant time with the
size function.

```
template<class T>
concept sized_range =
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 sized_range only if

- ranges::size(t) is , 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.

[ 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.

β 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 = see below;
```

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

- If derived_from<T, view_base> is true, true.
- Otherwise, if T is a specialization of class template initializer_list ([support.initlist]), set ([set]), multiset ([multiset]), unordered_set ([unord.set]), unordered_multiset ([unord.multiset]), or match_results ([re.results]), false.
- Otherwise, if both T and const T model range
and range_reference_t<T> is not the same type as
range_reference_t<const T>,
false. [ Note: Deep const-ness implies element ownership, whereas shallow const-ness implies reference semantics. β]
*end note* - Otherwise, true.

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 ([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>>>;
};
```

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.