A Range is a concept
similar to the STL Container
concept. A Range provides iterators for accessing a half-open range [first,one_past_last) of elements and provides information about
the number of elements in the Range. However, a Range has fewer requirements
than a Container.

The motivation for the Range concept is that there are many useful Container-like
types that do not meet the full requirements of Container, and many algorithms
that can be written with this reduced set of requirements. In particular,
a Range does not necessarily

own the elements that can be accessed through it,

have copy semantics,

Because of the second requirement, a Range object must be passed by (const
or non-const) reference in generic code.

The operations that can be performed on a Range is dependent on the traversal
category of the underlying iterator type. Therefore the range concepts
are named to reflect which traversal category its iterators support. See
also terminology and style guidelines. for more information about naming
of ranges.

The concepts described below specifies associated types as metafunctions
and all functions as free-standing functions to allow for a layer of indirection.