[range.req]

# 25 Ranges library [[ranges]](./#ranges)

## 25.4 Range requirements [range.req]

### [25.4.1](#general) General [[range.req.general]](range.req.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1287)

Ranges are an abstraction that allows a C++ program
to operate on elements of data structures uniformly[.](#general-1.sentence-1)

Calling ranges​::​begin on a range returns an object
whose type models [input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6 Concept input_­or_­output_­iterator [iterator.concept.iterator]") ([[iterator.concept.iterator]](iterator.concept.iterator "24.3.4.6 Concept input_­or_­output_­iterator"))[.](#general-1.sentence-2)

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](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_­for [iterator.concept.sentinel]")<S, I>[.](#general-1.sentence-3)

The library formalizes the interfaces, semantics, and complexity of ranges
to enable algorithms and range adaptors that work efficiently
on different types of sequences[.](#general-1.sentence-4)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1299)

The [range](#concept:range "25.4.2 Ranges [range.range]") concept requires thatranges​::​begin and ranges​::​end return an iterator and a sentinel, respectively[.](#general-2.sentence-1)

The [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]") concept refines [range](#concept:range "25.4.2 Ranges [range.range]") with
the requirement that ranges​::​size be amortized O(1)[.](#general-2.sentence-2)

The [view](#concept:view "25.4.5 Views [range.view]") concept specifies requirements on
a [range](#concept:range "25.4.2 Ranges [range.range]") type to provide operations with predictable complexity[.](#general-2.sentence-3)

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1308)

Several refinements of [range](#concept:range "25.4.2 Ranges [range.range]") group requirements
that arise frequently in concepts and algorithms[.](#general-3.sentence-1)

Common ranges are ranges for whichranges​::​begin and ranges​::​end return objects of the same type[.](#general-3.sentence-2)

Random access ranges are ranges for which ranges​::​begin returns a type that models[random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]") ([[iterator.concept.random.access]](iterator.concept.random.access "24.3.4.13 Concept random_­access_­iterator"))[.](#general-3.sentence-3)

(Contiguous, bidirectional, forward, input, and output ranges
are defined similarly[.](#general-3.sentence-4))

Viewable ranges can be converted to views[.](#general-3.sentence-5)

### [25.4.2](#range.range) Ranges [[range.range]](range.range)

[1](#range.range-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1323)

The [range](#concept:range "25.4.2 Ranges [range.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[.](#range.range-1.sentence-1)

[ð](#concept:range)

`template<class T>
  concept [range](#concept:range "25.4.2 Ranges [range.range]") =
    requires(T& t) {
      ranges::begin(t);         // sometimes equality-preserving (see below)
      ranges::end(t);
    };
`

[2](#range.range-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1338)

Given an expression t such that decltype((t)) is T&,T models [range](#concept:range "25.4.2 Ranges [range.range]") only if

- [(2.1)](#range.range-2.1)

[ranges​::​begin(t), ranges​::​end(t))
 denotes a range ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General")),

- [(2.2)](#range.range-2.2)

bothranges​::​begin(t) andranges​::​end(t) are amortized constant time and non-modifying, and

- [(2.3)](#range.range-2.3)

if the type of ranges​::​begin(t) models[forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"), ranges​::​begin(t) is equality-preserving[.](#range.range-2.sentence-1)

[3](#range.range-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1355)

[*Note [1](#range.range-note-1)*:

Equality preservation of both ranges​::​begin andranges​::​end enables passing a range whose iterator
type models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]") to multiple
algorithms and making multiple passes over the range by repeated calls toranges​::​begin and ranges​::​end[.](#range.range-3.sentence-1)

Since ranges​::​begin is not required to be equality-preserving
when the return type does not model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"),
it is possible for repeated calls
to not return equal values or to not be well-defined[.](#range.range-3.sentence-2)

â *end note*]

[ð](#concept:borrowed_range)

`template<class T>
  concept [borrowed_range](#concept:borrowed_range "25.4.2 Ranges [range.range]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
`

[4](#range.range-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1376)

Let U be remove_reference_t<T> if T is an rvalue reference type, and T otherwise[.](#range.range-4.sentence-1)

Given a variable u of type U,T models [borrowed_range](#concept:borrowed_range "25.4.2 Ranges [range.range]") only if
the validity of iterators obtained from u is not tied to the lifetime of that variable[.](#range.range-4.sentence-2)

[5](#range.range-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1384)

[*Note [2](#range.range-note-2)*:

Since the validity of iterators is not tied to the lifetime of
a variable whose type models [borrowed_range](#concept:borrowed_range "25.4.2 Ranges [range.range]"),
a function with a parameter of such a type can
return iterators obtained from it without danger of dangling[.](#range.range-5.sentence-1)

â *end note*]

[ð](#lib:enable_borrowed_range)

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

[6](#range.range-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1400)

*Remarks*: Pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"), users may specialize enable_borrowed_range for cv-unqualified program-defined types[.](#range.range-6.sentence-1)

Such specializations shall be
usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")) and
have type const bool[.](#range.range-6.sentence-2)

[7](#range.range-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1408)

[*Example [1](#range.range-example-1)*:

Each specialization S of class template subrange ([[range.subrange]](range.subrange "25.5.4 Sub-ranges"))
models [borrowed_range](#concept:borrowed_range "25.4.2 Ranges [range.range]") because

- [(7.1)](#range.range-7.1)

enable_borrowed_range<S> is specialized
to have the value true, and

- [(7.2)](#range.range-7.2)

S's iterators
do not have validity tied to the lifetime of an S object
because they are âborrowedâ from some other range[.](#range.range-7.sentence-1)

â *end example*]

### [25.4.3](#range.approximately.sized) Approximately sized ranges [[range.approximately.sized]](range.approximately.sized)

[1](#range.approximately.sized-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1427)

The [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") concept refines [range](#concept:range "25.4.2 Ranges [range.range]") with the requirement that
an approximation of the number of elements in the range
can be determined in amortized constant time using ranges​::​reserve_hint[.](#range.approximately.sized-1.sentence-1)

[ð](#concept:approximately_sized_range)

`template<class T>
  concept [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> && requires(T& t) { ranges::reserve_hint(t); };
`

[2](#range.approximately.sized-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1440)

Given an lvalue t of type remove_reference_t<T>,T models [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") only if

- [(2.1)](#range.approximately.sized-2.1)

ranges​::​reserve_hint(t) is amortized O(1),
does not modify t, and
has a value that
is not negative and is representable in range_difference_t<T>, and

- [(2.2)](#range.approximately.sized-2.2)

if iterator_t<T> models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"),ranges​::​reserve_hint(t) is well-defined
regardless of the evaluation of ranges​::​begin(t)[.](#range.approximately.sized-2.sentence-1)
  [*Note [1](#range.approximately.sized-note-1)*:
  ranges​::​reserve_hint(t) is otherwise not required to be well-defined
after evaluating ranges​::​begin(t)[.](#range.approximately.sized-2.2.sentence-2)
  For example,
it is possible for ranges​::​reserve_hint(t) to be well-defined for
an [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") whose
iterator type does not model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]") only if evaluated before the first call to ranges​::​begin(t)[.](#range.approximately.sized-2.2.sentence-3)
 â *end note*]

### [25.4.4](#range.sized) Sized ranges [[range.sized]](range.sized)

[1](#range.sized-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1467)

The [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]") concept
refines [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]") with
the requirement that the number of elements in the range can be determined
in amortized constant time using ranges​::​size[.](#range.sized-1.sentence-1)

[ð](#concept:sized_range)

`template<class T>
  concept [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]") =
    [approximately_sized_range](#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<T> && requires(T& t) { ranges::size(t); };
`

[2](#range.sized-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1480)

Given an lvalue t of type remove_reference_t<T>, T models [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]") only if

- [(2.1)](#range.sized-2.1)

ranges​::​size(t) is amortized O(1), does not modify t,
and is equal to ranges​::​distance(​ranges​::​begin(t), ranges​::​end(t)), and

- [(2.2)](#range.sized-2.2)

if iterator_t<T> models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]"),ranges​::​size(t) is well-defined regardless of the evaluation ofranges​::​begin(t)[.](#range.sized-2.sentence-1)
  [*Note [1](#range.sized-note-1)*:
  ranges​::​size(t) is otherwise not required to be
well-defined after evaluating ranges​::​begin(t)[.](#range.sized-2.2.sentence-2)
  For example, it is possible for ranges​::​size(t) to be well-defined
for a [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]") whose iterator type
does not model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]") only if evaluated before the first call to ranges​::​begin(t)[.](#range.sized-2.2.sentence-3)
 â *end note*]

[ð](#lib:disable_sized_range)

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

[3](#range.sized-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1508)

*Remarks*: Pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"),
users may specialize disable_sized_range for cv-unqualified program-defined types[.](#range.sized-3.sentence-1)

Such specializations shall
be usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")) and
have type const bool[.](#range.sized-3.sentence-2)

[4](#range.sized-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1517)

[*Note [2](#range.sized-note-2)*:

disable_sized_range allows use of [range](#concept:range "25.4.2 Ranges [range.range]") types with the library
that satisfy but do not in fact model [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]")[.](#range.sized-4.sentence-1)

â *end note*]

### [25.4.5](#range.view) Views [[range.view]](range.view)

[1](#range.view-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1526)

The [view](#concept:view "25.4.5 Views [range.view]") concept specifies the requirements of a [range](#concept:range "25.4.2 Ranges [range.range]") type
that has the semantic properties below,
which make it suitable for use in
constructing range adaptor pipelines ([[range.adaptors]](range.adaptors "25.7 Range adaptors"))[.](#range.view-1.sentence-1)

[ð](#concept:view)

`template<class T>
  concept [view](#concept:view "25.4.5 Views [range.view]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> && [movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]")<T> && enable_view<T>;
`

[2](#range.view-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1539)

T models [view](#concept:view "25.4.5 Views [range.view]") only if

- [(2.1)](#range.view-2.1)

T has O(1) move construction; and

- [(2.2)](#range.view-2.2)

move assignment of an object of type T is no more complex than destruction followed by move construction; and

- [(2.3)](#range.view-2.3)

if N copies and/or moves are made from an object of type T that contained M elements,
then those N objects have O(N+M) destruction; and

- [(2.4)](#range.view-2.4)

[copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<T> is false, orT has O(1) copy construction; and

- [(2.5)](#range.view-2.5)

[copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<T> is false, or
copy assignment of an object of type T is no more complex than destruction followed by copy construction[.](#range.view-2.sentence-1)

[3](#range.view-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1564)

[*Note [1](#range.view-note-1)*:

The constraints on copying and moving imply that
a moved-from object of type T has O(1) destruction[.](#range.view-3.sentence-1)

â *end note*]

[4](#range.view-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1570)

[*Example [1](#range.view-example-1)*:

Examples of views are:

- [(4.1)](#range.view-4.1)

  A [range](#concept:range "25.4.2 Ranges [range.range]") type that wraps a pair of iterators[.](#range.view-4.1.sentence-1)

- [(4.2)](#range.view-4.2)

  A [range](#concept:range "25.4.2 Ranges [range.range]") type that holds its elements by shared_ptr and shares ownership with all its copies[.](#range.view-4.2.sentence-1)

- [(4.3)](#range.view-4.3)

  A [range](#concept:range "25.4.2 Ranges [range.range]") type that generates its elements on demand[.](#range.view-4.3.sentence-1)

A container such as vector<string> does not meet the semantic requirements of [view](#concept:view "25.4.5 Views [range.view]") since copying the container copies all of the elements,
which cannot be done in constant time[.](#range.view-4.sentence-2)

â *end example*]

[5](#range.view-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1589)

Since the difference between [range](#concept:range "25.4.2 Ranges [range.range]") and [view](#concept:view "25.4.5 Views [range.view]") is largely
semantic, the two are differentiated with the help of enable_view[.](#range.view-5.sentence-1)

[ð](#lib:enable_view)

`template<class T>
  constexpr bool is-derived-from-view-interface = see below;            // exposition only
template<class T>
  constexpr bool enable_view =
    [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")<T, view_base> || is-derived-from-view-interface<T>;
`

[6](#range.view-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1603)

For a type T,*is-derived-from-view-interface*<T> is true if and only ifT has exactly one public base class view_interface<U> for some type U andT has no base classes of type view_interface<V> for any other type V[.](#range.view-6.sentence-1)

[7](#range.view-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1612)

*Remarks*: Pursuant to [[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"), users may specialize enable_view to true for cv-unqualified program-defined types that model [view](#concept:view "25.4.5 Views [range.view]"),
and false for types that do not[.](#range.view-7.sentence-1)

Such specializations shall
be usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")) and
have type const bool[.](#range.view-7.sentence-2)

### [25.4.6](#range.refinements) Other range refinements [[range.refinements]](range.refinements)

[1](#range.refinements-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1625)

The [output_range](#concept:output_range "25.4.6 Other range refinements [range.refinements]") concept specifies requirements of a[range](#concept:range "25.4.2 Ranges [range.range]") type for which ranges​::​begin returns
a model of [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10 Concept output_­iterator [iterator.concept.output]") ([[iterator.concept.output]](iterator.concept.output "24.3.4.10 Concept output_­iterator"))[.](#range.refinements-1.sentence-1)

[input_range](#concept:input_range "25.4.6 Other range refinements [range.refinements]"), [forward_range](#concept:forward_range "25.4.6 Other range refinements [range.refinements]"), [bidirectional_range](#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"),
and [random_access_range](#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") are defined similarly[.](#range.refinements-1.sentence-2)

[ð](#range.refinements-itemdecl:1)

`template<class R, class T>
  concept [output_range](#concept:output_range "25.4.6 Other range refinements [range.refinements]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<R> && [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10 Concept output_­iterator [iterator.concept.output]")<iterator_t<R>, T>;

template<class T>
  concept [input_range](#concept:input_range "25.4.6 Other range refinements [range.refinements]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> && [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]")<iterator_t<T>>;

template<class T>
  concept [forward_range](#concept:forward_range "25.4.6 Other range refinements [range.refinements]") =
    [input_range](#concept:input_range "25.4.6 Other range refinements [range.refinements]")<T> && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")<iterator_t<T>>;

template<class T>
  concept [bidirectional_range](#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]") =
    [forward_range](#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<T> && [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]")<iterator_t<T>>;

template<class T>
  concept [random_access_range](#concept:random_access_range "25.4.6 Other range refinements [range.refinements]") =
    [bidirectional_range](#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<T> && [random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")<iterator_t<T>>;
`

[2](#range.refinements-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1654)

[contiguous_range](#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") additionally requires that
the ranges​::​data customization point object ([[range.prim.data]](range.prim.data "25.3.14 ranges​::​data"))
is usable with the range[.](#range.refinements-2.sentence-1)

[ð](#concept:contiguous_range)

`template<class T>
  concept [contiguous_range](#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") =
    [random_access_range](#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<T> && [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]")<iterator_t<T>> &&
    requires(T& t) {
      { ranges::data(t) } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<add_pointer_t<range_reference_t<T>>>;
    };
`

[3](#range.refinements-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1668)

Given an expression t such that decltype((t)) is T&,T models [contiguous_range](#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") only ifto_address(​ranges​::​begin(t)) == ranges​::​data(t) is true[.](#range.refinements-3.sentence-1)

[4](#range.refinements-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1674)

The [common_range](#concept:common_range "25.4.6 Other range refinements [range.refinements]") concept specifies requirements of
a [range](#concept:range "25.4.2 Ranges [range.range]") type for which ranges​::​begin andranges​::​end return objects of the same type[.](#range.refinements-4.sentence-1)

[*Example [1](#range.refinements-example-1)*:

The standard containers ([[containers]](containers "23 Containers library")) model [common_range](#concept:common_range "25.4.6 Other range refinements [range.refinements]")[.](#range.refinements-4.sentence-2)

â *end example*]

[ð](#concept:common_range)

`template<class T>
  concept [common_range](#concept:common_range "25.4.6 Other range refinements [range.refinements]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> && [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<iterator_t<T>, sentinel_t<T>>;
`

[ð](#range.refinements-itemdecl:4)

`template<class R>
  constexpr bool is-initializer-list = see below;               // exposition only
`

[5](#range.refinements-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1694)

For a type R,*is-initializer-list*<R> is true if and only ifremove_cvref_t<R> is a specialization of initializer_list[.](#range.refinements-5.sentence-1)

[6](#range.refinements-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1700)

The [viewable_range](#concept:viewable_range "25.4.6 Other range refinements [range.refinements]") concept specifies the requirements of a[range](#concept:range "25.4.2 Ranges [range.range]") type that can be converted to a view safely[.](#range.refinements-6.sentence-1)

[ð](#concept:viewable_range)

`template<class T>
  concept [viewable_range](#concept:viewable_range "25.4.6 Other range refinements [range.refinements]") =
    [range](#concept:range "25.4.2 Ranges [range.range]")<T> &&
    (([view](#concept:view "25.4.5 Views [range.view]")<remove_cvref_t<T>> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<remove_cvref_t<T>, T>) ||
     (![view](#concept:view "25.4.5 Views [range.view]")<remove_cvref_t<T>> &&
      (is_lvalue_reference_v<T> || ([movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]")<remove_reference_t<T>> && !is-initializer-list<T>))));
`

[7](#range.refinements-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1713)

The [constant_range](#concept:constant_range "25.4.6 Other range refinements [range.refinements]") concept specifies the requirements of a[range](#concept:range "25.4.2 Ranges [range.range]") type whose elements are not modifiable[.](#range.refinements-7.sentence-1)

[ð](#concept:constant_range)

`template<class T>
  concept [constant_range](#concept:constant_range "25.4.6 Other range refinements [range.refinements]") =
    [input_range](#concept:input_range "25.4.6 Other range refinements [range.refinements]")<T> && [constant-iterator](const.iterators.alias#concept:constant-iterator "24.5.3.2 Alias templates [const.iterators.alias]")<iterator_t<T>>;
`

[8](#range.refinements-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1723)

The exposition-only concept [*sized-random-access-range*](#concept:sized-random-access-range "25.4.6 Other range refinements [range.refinements]") specifies the requirements of a [range](#concept:range "25.4.2 Ranges [range.range]") type
that is sized and allows random access to its elements[.](#range.refinements-8.sentence-1)

[ð](#concept:sized-random-access-range)

`template<class T>
  concept [sized-random-access-range](#concept:sized-random-access-range "25.4.6 Other range refinements [range.refinements]") =           // exposition only
    [random_access_range](#concept:random_access_range "25.4.6 Other range refinements [range.refinements]")<R> && [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>;
`

[*Note [1](#range.refinements-note-1)*:

This concept constrains some parallel algorithm overloads;
see [[algorithms]](algorithms "26 Algorithms library")[.](#range.refinements-sentence-1)

â *end note*]
