std::ranges::borrowed_range, std::ranges::enable_borrowed_range - cppreference.com

From cppreference.com

Defined in header

<ranges>

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

range

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

program-defined types

which model borrowed_range, and false for types which do not. Such specializations shall be usable in

constant expression

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:

std::basic_string_view

std::span

std::ranges::subrange

std::ranges::ref_view

std::ranges::empty_view

std::ranges::iota_view

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:

std::ranges::common_view

std::ranges::drop_view

std::ranges::drop_while_view

std::ranges::elements_view

std::ranges::owning_view

std::ranges::reverse_view

std::ranges::take_view

The underlying view V must also satisfy

forward_range

.

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:

std::ranges::zip_view

(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)

[edit]