3361. safe_range<SomeRange&> case

Section: 25.4.2 [range.range] Status: C++23 Submitter: Johel Ernesto Guerrero Peña Opened: 2019-12-19 Last modified: 2023-11-22

Priority: 3

View all other issues in [range.range].

View all issues with C++23 status.

Discussion:

25.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 25.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, aA 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 25.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 objecta 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]