From cppreference.com
Defined in header
template<classR>conceptborrowed_range=ranges::range<R>&&(std::is_lvalue_reference_v<R>||ranges::enable_borrowed_range<std::remove_cvref_t<R>>); (1) (since C++20)template<classR>constexprboolenable_borrowed_range=false; (2) (since C++20)1) The concept borrowed_range defines the requirements of a range such that a function can take it by value and return iterators obtained from it without danger of dangling.
2) The enable_borrowed_range variable template is used to indicate whether a
is a borrowed_range. The primary template is defined as false.
Semantic requirements
Let U be std::remove_reference_t<T> if T is an rvalue reference type, and T otherwise. Given a variable u of type U, T models borrowed_range only if the validity of iterators obtained from u is not tied to the lifetime of that variable.
Specializations
A program may specialize enable_borrowed_range to true for cv-unqualified
which model borrowed_range, and false for types which do not. Such specializations shall be usable in
and have type constbool.
Unconditionally borrowed ranges in the standard library
Specializations of enable_borrowed_range for all specializations of the following standard templates are defined as true:
Conditionally borrowed ranges in the standard library
Specialization of enable_borrowed_range for the following standard range adaptors are defined as true if and only if std::ranges::enable_borrowed_range<V> is true, where V is the underlying view type:
The underlying view V must also satisfy
.
Specialization of enable_borrowed_range for the following standard range adaptors are defined as true if and only if (std::ranges::enable_borrowed_range<Vs>&&...) is true, where Vs... are all view types it adapts:
(since C++23)Example
Demonstrates the specializations of enable_borrowed_range for program defined types. Such specializations protect against potentially dangling results.
Run this code
#include<algorithm>#include<array>#include<cstddef>#include<iostream>#include<ranges>#include<span>#include<type_traits>template<typenameT,std::size_tN>structMyRange:std::array<T,N>{};template<typenameT,std::size_tN>constexprboolstd::ranges::enable_borrowed_range<MyRange<T,N>>=false;template<typenameT,std::size_tN>structMyBorrowedRange:std::span<T,N>{};template<typenameT,std::size_tN>constexprboolstd::ranges::enable_borrowed_range<MyBorrowedRange<T,N>>=true;intmain(){static_assert(std::ranges::range<MyRange<int,8>>);static_assert(std::ranges::borrowed_range<MyRange<int,8>>==false);static_assert(std::ranges::range<MyBorrowedRange<int,8>>);static_assert(std::ranges::borrowed_range<MyBorrowedRange<int,8>>==true);autogetMyRangeByValue=[]{returnMyRange<int,4>{{1,2,42,3}};};autodangling_iter=std::ranges::max_element(getMyRangeByValue());static_assert(std::is_same_v<std::ranges::dangling,decltype(dangling_iter)>);// *dangling_iter; // compilation error (i.e. dangling protection works.)automy=MyRange<int,4>{{1,2,42,3}};autovalid_iter=std::ranges::max_element(my);std::cout<<*valid_iter<<' ';// OK: 42autogetMyBorrowedRangeByValue=[]{staticintsa[4]{1,2,42,3};returnMyBorrowedRange<int,std::size(sa)>{sa};};autovalid_iter2=std::ranges::max_element(getMyBorrowedRangeByValue());std::cout<<*valid_iter2<<'\n';// OK: 42}Output:
42 42 See also
(C++20)
a placeholder type indicating that an iterator or a subrange should not be returned since it would be dangling
(class)