[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]")[.](#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 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 concept [borrowed_range](#concept:borrowed_range "25.4.2 Ranges [range.range]") = [range](#concept:range "25.4.2 Ranges [range.range]") && (is_lvalue_reference_v || enable_borrowed_range>); ` [4](#range.range-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1376) Let U be remove_reference_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 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 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 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]") && 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 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, and - [(2.2)](#range.approximately.sized-2.2) if iterator_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 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]") && 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 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 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 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 concept [view](#concept:view "25.4.5 Views [range.view]") = [range](#concept:range "25.4.2 Ranges [range.range]") && [movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]") && enable_view; ` [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]") 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]") 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 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 constexpr bool is-derived-from-view-interface = see below; // exposition only template constexpr bool enable_view = [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]") || is-derived-from-view-interface; ` [6](#range.view-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1603) For a type T,*is-derived-from-view-interface* is true if and only ifT has exactly one public base class view_interface for some type U andT has no base classes of type view_interface 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 concept [output_range](#concept:output_range "25.4.6 Other range refinements [range.refinements]") = [range](#concept:range "25.4.2 Ranges [range.range]") && [output_iterator](iterator.concept.output#concept:output_iterator "24.3.4.10 Concept output_­iterator [iterator.concept.output]"), T>; template concept [input_range](#concept:input_range "25.4.6 Other range refinements [range.refinements]") = [range](#concept:range "25.4.2 Ranges [range.range]") && [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9 Concept input_­iterator [iterator.concept.input]")>; template 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]") && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_­iterator [iterator.concept.forward]")>; template 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]") && [bidirectional_iterator](iterator.concept.bidir#concept:bidirectional_iterator "24.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]")>; template 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]") && [random_access_iterator](iterator.concept.random.access#concept:random_access_iterator "24.3.4.13 Concept random_­access_­iterator [iterator.concept.random.access]")>; ` [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 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]") && [contiguous_iterator](iterator.concept.contiguous#concept:contiguous_iterator "24.3.4.14 Concept contiguous_­iterator [iterator.concept.contiguous]")> && requires(T& t) { { ranges::data(t) } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")>>; }; ` [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 concept [common_range](#concept:common_range "25.4.6 Other range refinements [range.refinements]") = [range](#concept:range "25.4.2 Ranges [range.range]") && [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]"), sentinel_t>; ` [🔗](#range.refinements-itemdecl:4) `template 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* is true if and only ifremove_cvref_t 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 concept [viewable_range](#concept:viewable_range "25.4.6 Other range refinements [range.refinements]") = [range](#concept:range "25.4.2 Ranges [range.range]") && (([view](#concept:view "25.4.5 Views [range.view]")> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]"), T>) || (![view](#concept:view "25.4.5 Views [range.view]")> && (is_lvalue_reference_v || ([movable](concepts.object#concept:movable "18.6 Object concepts [concepts.object]")> && !is-initializer-list)))); ` [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 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]") && [constant-iterator](const.iterators.alias#concept:constant-iterator "24.5.3.2 Alias templates [const.iterators.alias]")>; ` [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 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]") && [sized_range](#concept:sized_range "25.4.4 Sized ranges [range.sized]"); ` [*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*]