[range.range] # 25 Ranges library [[ranges]](./#ranges) ## 25.4 Range requirements [[range.req]](range.req#range.range) ### 25.4.2 Ranges [range.range] [1](#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[.](#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](#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)](#2.1) [ranges​::​begin(t), ranges​::​end(t)) denotes a range ([[iterator.requirements.general]](iterator.requirements.general "24.3.1 General")), - [(2.2)](#2.2) bothranges​::​begin(t) andranges​::​end(t) are amortized constant time and non-modifying, and - [(2.3)](#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[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1355) [*Note [1](#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[.](#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[.](#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](#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[.](#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[.](#4.sentence-2) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1384) [*Note [2](#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[.](#5.sentence-1) — *end note*] [🔗](#lib:enable_borrowed_range) `template constexpr bool enable_borrowed_range = false; ` [6](#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[.](#6.sentence-1) Such specializations shall be usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")) and have type const bool[.](#6.sentence-2) [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L1408) [*Example [1](#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)](#7.1) enable_borrowed_range is specialized to have the value true, and - [(7.2)](#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[.](#7.sentence-1) — *end example*]