This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

### 3361. `safe_range<SomeRange&>` case

Section: 24.4.2 [range.range] Status: WP Submitter: Johel Ernesto Guerrero Peña Opened: 2019-12-19 Last modified: 2021-10-14

Priority: 3

View all issues with WP status.

Discussion:

24.5.5 [range.dangling] p2 hints at how `safe_range` should allow lvalue ranges to model it. However, its wording doesn't take into account that case.

[2020-01 Priority set to 3 after review on the reflector.]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4842.

> 1. Modify 24.4.2 [range.range] as indicated:

>    >     template<class T>
>    >       concept safe_range =
>    >         range<T> &&
>    >           (is_lvalue_reference_v<T> || enable_safe_range<remove_cvref_t<T>>);

>    > > -5- Given an expression `E` such that `decltype((E))` is `T`,A type `T` models `safe_range` only if:

>    > > 1. (5.1) — `is_lvalue_reference_v<T>` is `true`, or

>    > > 2. (5.2) — given an expression `E` such that `decltype((E))` is `T`, if the validity of iterators obtained from the object denoted by `E` is not tied to the lifetime of that object.

>    > > -6- [Note: Since the validity of iterators is not tied to the lifetime of an object whose type models `safe_range`, a A function can accept arguments of such a type that models `safe_range` by value and return iterators obtained from it without danger of dangling. — end note]

[2021-05-19 Tim updates wording]

The new wording below attempts to keep the "borrowed" property generally applicable to all models of `borrowed_range`, instead of bluntly carving out lvalue reference types.

[2021-09-20; Reflector poll]

Set status to Tentatively Ready after five votes in favour during reflector poll in June.

[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4885.

1. Modify 24.4.2 [range.range] as indicated:

   >     template<class T>
   >       concept borrowed_range =
   >         range<T> &&
   >           (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);

   > > -5- Let `U` be `remove_reference_t<T>` if `T` is an rvalue reference type, and `T` otherwise. Given an expression `E` such that `decltype((E))` is `T` a variable `u` of type `U`, `T` models `borrowed_range` only if the validity of iterators obtained from the object denoted by `E` u is not tied to the lifetime of that object variable.

   > > -6- [Note: Since the validity of iterators is not tied to the lifetime of an object a variable whose type models `borrowed_range`, a function can accept arguments of with a parameter of such a type by value and can return iterators obtained from it without danger of dangling. — end note]