Files
2025-10-25 03:02:53 +03:00

544 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.6Concept input_­or_­output_­iterator[iterator.concept.iterator]") ([[iterator.concept.iterator]](iterator.concept.iterator "24.3.4.6Concept 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.7Concept 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.2Ranges[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.4Sized ranges[range.sized]") concept refines [range](#concept:range "25.4.2Ranges[range.range]") with
the requirement that ranges::size be amortized O(1)[.](#general-2.sentence-2)
The [view](#concept:view "25.4.5Views[range.view]") concept specifies requirements on
a [range](#concept:range "25.4.2Ranges[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.2Ranges[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.13Concept random_­access_­iterator[iterator.concept.random.access]") ([[iterator.concept.random.access]](iterator.concept.random.access "24.3.4.13Concept 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.2Ranges[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.2Ranges[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.2Ranges[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.1General")),
- [(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.11Concept 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.11Concept 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.11Concept 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.2Ranges[range.range]") =
[range](#concept:range "25.4.2Ranges[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.2Ranges[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.2Ranges[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.1Namespace 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.7Constant 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.4Sub-ranges"))
models [borrowed_range](#concept:borrowed_range "25.4.2Ranges[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.3Approximately sized ranges[range.approximately.sized]") concept refines [range](#concept:range "25.4.2Ranges[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.3Approximately sized ranges[range.approximately.sized]") =
[range](#concept:range "25.4.2Ranges[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.3Approximately 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.11Concept 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.3Approximately sized ranges[range.approximately.sized]") whose
iterator type does not model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept 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.4Sized ranges[range.sized]") concept
refines [approximately_sized_range](#concept:approximately_sized_range "25.4.3Approximately 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.4Sized ranges[range.sized]") =
[approximately_sized_range](#concept:approximately_sized_range "25.4.3Approximately 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.4Sized 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.11Concept 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.4Sized ranges[range.sized]") whose iterator type
does not model [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept 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.1Namespace 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.7Constant 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.2Ranges[range.range]") types with the library
that satisfy but do not in fact model [sized_range](#concept:sized_range "25.4.4Sized 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.5Views[range.view]") concept specifies the requirements of a [range](#concept:range "25.4.2Ranges[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.7Range adaptors"))[.](#range.view-1.sentence-1)
[🔗](#concept:view)
`template<class T>
concept [view](#concept:view "25.4.5Views[range.view]") =
[range](#concept:range "25.4.2Ranges[range.range]")<T> && [movable](concepts.object#concept:movable "18.6Object 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.5Views[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.14Concept 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.6Object 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.2Ranges[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.2Ranges[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.2Ranges[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.5Views[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.2Ranges[range.range]") and [view](#concept:view "25.4.5Views[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.3Concept 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.1Namespace std"), users may specialize enable_view to true for cv-unqualified program-defined types that model [view](#concept:view "25.4.5Views[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.7Constant 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.6Other range refinements[range.refinements]") concept specifies requirements of a[range](#concept:range "25.4.2Ranges[range.range]") type for which ranges::begin returns
a model of [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10Concept output_­iterator[iterator.concept.output]") ([[iterator.concept.output]](iterator.concept.output "24.3.4.10Concept output_­iterator"))[.](#range.refinements-1.sentence-1)
[input_range](#concept:input_range "25.4.6Other range refinements[range.refinements]"), [forward_range](#concept:forward_range "25.4.6Other range refinements[range.refinements]"), [bidirectional_range](#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]"),
and [random_access_range](#concept:random_access_range "25.4.6Other 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.6Other range refinements[range.refinements]") =
[range](#concept:range "25.4.2Ranges[range.range]")<R> && [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10Concept output_­iterator[iterator.concept.output]")<iterator_t<R>, T>;
template<class T>
concept [input_range](#concept:input_range "25.4.6Other range refinements[range.refinements]") =
[range](#concept:range "25.4.2Ranges[range.range]")<T> && [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9Concept input_­iterator[iterator.concept.input]")<iterator_t<T>>;
template<class T>
concept [forward_range](#concept:forward_range "25.4.6Other range refinements[range.refinements]") =
[input_range](#concept:input_range "25.4.6Other range refinements[range.refinements]")<T> && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept forward_­iterator[iterator.concept.forward]")<iterator_t<T>>;
template<class T>
concept [bidirectional_range](#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]") =
[forward_range](#concept:forward_range "25.4.6Other range refinements[range.refinements]")<T> && [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12Concept bidirectional_­iterator[iterator.concept.bidir]")<iterator_t<T>>;
template<class T>
concept [random_access_range](#concept:random_access_range "25.4.6Other range refinements[range.refinements]") =
[bidirectional_range](#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]")<T> && [random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13Concept 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.6Other range refinements[range.refinements]") additionally requires that
the ranges::data customization point object ([[range.prim.data]](range.prim.data "25.3.14ranges::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.6Other range refinements[range.refinements]") =
[random_access_range](#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<T> && [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14Concept contiguous_­iterator[iterator.concept.contiguous]")<iterator_t<T>> &&
requires(T& t) {
{ ranges::data(t) } -> [same_as](concept.same#concept:same_as "18.4.2Concept 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.6Other 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.6Other range refinements[range.refinements]") concept specifies requirements of
a [range](#concept:range "25.4.2Ranges[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 "23Containers library")) model [common_range](#concept:common_range "25.4.6Other 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.6Other range refinements[range.refinements]") =
[range](#concept:range "25.4.2Ranges[range.range]")<T> && [same_as](concept.same#concept:same_as "18.4.2Concept 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.6Other range refinements[range.refinements]") concept specifies the requirements of a[range](#concept:range "25.4.2Ranges[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.6Other range refinements[range.refinements]") =
[range](#concept:range "25.4.2Ranges[range.range]")<T> &&
(([view](#concept:view "25.4.5Views[range.view]")<remove_cvref_t<T>> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<remove_cvref_t<T>, T>) ||
(![view](#concept:view "25.4.5Views[range.view]")<remove_cvref_t<T>> &&
(is_lvalue_reference_v<T> || ([movable](concepts.object#concept:movable "18.6Object 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.6Other range refinements[range.refinements]") concept specifies the requirements of a[range](#concept:range "25.4.2Ranges[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.6Other range refinements[range.refinements]") =
[input_range](#concept:input_range "25.4.6Other range refinements[range.refinements]")<T> && [constant-iterator](const.iterators.alias#concept:constant-iterator "24.5.3.2Alias 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.6Other range refinements[range.refinements]") specifies the requirements of a [range](#concept:range "25.4.2Ranges[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.6Other range refinements[range.refinements]") = // exposition only
[random_access_range](#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<R> && [sized_range](#concept:sized_range "25.4.4Sized ranges[range.sized]")<R>;
`
[*Note [1](#range.refinements-note-1)*:
This concept constrains some parallel algorithm overloads;
see [[algorithms]](algorithms "26Algorithms library")[.](#range.refinements-sentence-1)
— *end note*]