3909. Issues about viewable_range

Section: 99 [ranges.refinements], 26.7.2 [range.adaptor.object] Status: Tentatively NAD Submitter: Jiang An Opened: 2023-03-27 Last modified: 2023-06-01 14:31:30 UTC

Priority: Not Prioritized

View all issues with Tentatively NAD status.


After LWG 3724, views::all is well-constrained for view types, and the constraints are stronger than viewable_range. The difference is that given an expression such that decltype gives R, when decay_t<R> is a view type and the implicit conversion of R to decay_t<R> is forbidden, views::all rejects the expression, but viewable_range may accept R. So I think we should remove the additional constraints on views::all_t.

While viewable_range is probably not introducing any additional constraint within the standard library, I think it is still useful to express the constraints on views::all, so it should be slightly adjusted to match views::all.

Furthermore, viewable_range is currently used in 26.7.2 [range.adaptor.object], but given P2378R3 relaxed the requirements for range adaptor closure objects, I think we should also apply similar relaxation for range adaptor objects. This should have no impact on standard range adaptor objects.

[2023-06-01; Reflector poll]

Set status to Tentatively NAD after three votes in favour during reflector poll.

"First change is pointless. Second change is a duplicate of 3896. Range adaptors return a view over their first argument, so they need to require it's a viewable_range."

Proposed resolution:

This wording is relative to N4944.

  1. Change the definition of views::all_t in 26.2 [ranges.syn] as indicated:

       template<viewable_rangeclass R>
          using all_t = decltype(all(declval<R>()));          // freestanding
  2. Change the definition of viewable_range in 26.4.5 [range.refinements] as indicated:

    -6- 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> &&
        ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T> convertible_to<T, remove_cvref_t<T>>) ||
         (!view<remove_cvref_t<T>> &&
          (is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
  3. Change 26.7.2 [range.adaptor.object] as indicated:

    -6- A range adaptor object is a customization point object ( [customization.point.object]) that accepts a viewable_rangerange as its first argument and returns a view.


    -8- If a range adaptor object adaptor accepts more than one argument, then let range be an expression such that decltype((range)) models viewable_rangerange, let args... be arguments such that adaptor(range, args...) is a well-formed expression as specified in the rest of subclause 26.7 [range.adaptors], and let BoundArgs be a pack that denotes decay_t<decltype((args))>.... The expression adaptor(args...) produces a range adaptor closure object f that is a perfect forwarding call wrapper (22.10.4 [func.require]) with the following properties: [...]