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.

### 3481. `viewable_range` mishandles lvalue move-only views

Section: 26.4.5 [range.refinements] Status: WP Submitter: Casey Carter Opened: 2020-08-29 Last modified: 2021-06-07

Priority: 2

View all other issues in [range.refinements].

View all issues with WP status.

Discussion:

The `viewable_range concept` (26.4.5 [range.refinements]) and the `views:all` range adaptor (26.7.6 [range.all]) are duals: `viewable_range` is intended to admit exactly types `T` for which `views::all(declval<T>())` is well-formed. (Recall that `views::all(meow)` is a prvalue whose type models `view` when it is well-formed.) Before the addition of move-only view types to the design, this relationship was in place (modulo an incredibly pathological case: a `volatile` value of a view type with `volatile`-qualified `begin` and `end` models `viewable_range` but is rejected by `views::all` unless it also has a `volatile`-qualified copy constructor and copy assignment operator). Adding move-only views to the design punches a bigger hole, however: `viewable_range` admits lvalues of move-only view types for which `views::all` is ill-formed because these lvalues cannot be decay-copied.

It behooves us to restore the correspondence between `viewable_range` and `views::all` so that instantiations of components constrained with `viewable_range` (which often appears indirectly as `views::all_t<R>` in deduction guides) continue to be well-formed when the constraints are satisfied.

[2020-09-06; Reflector prioritization]

Set priority to 2 during reflector discussions.

[2021-05-24; Reflector poll]

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

[2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4861.

1. Modify 26.4.5 [range.refinements] as indicated:

   > -5- The `viewable_range` concept specifies the requirements of a `range` type that can be converted to a `view` safely.

   >     template<class T>
   >       concept viewable_range =
   >         range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
   >         ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
   >         (!view<remove_cvref_t<T>> && borrowed_range<T>));