The definition of viewable_range is not quite right
Hewill Kang

Created on 2023-02-27.00:00:00 last changed 1 week ago


Date: 2023-03-22.22:40:39

Proposed resolution:

This wording is relative to N4928.

  1. Modify [range.refinements] as indicated:

    template<class T>
      concept viewable_range =
        range<T> &&
        ((view<remove_cvref_t<T>> && convertible_to<T, remove_cvref_t<T>>constructible_from<remove_cvref_t<T>, T>) ||
         (!view<remove_cvref_t<T>> &&
          (is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
Date: 2023-03-15.00:00:00

[ 2023-03-22; Reflector poll ]

Set priority to 4 after reflector poll. "About as contrived as it gets." "Add generic front matter telling users the library doesn't support types with explicit copy constructors."

Date: 2023-02-27.00:00:00

The requirements of viewable_range for view type is view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>, that is, when the decayed type of T models view, it must be constructible from T.

This part of the constraint corresponds to first bullet of views::all ([range.all.general]), which returns decay-copy(E) if the decayed type of E models view.

However, decay-copy(E) constraints convertible_to<T, decay_t<T>> which is a stronger requirement than constructible_from, which is reflected in its rejection of types with explicit copy constructors.

This inconsistency is such that the following causes the range adapter to produce a hard error when invoked (online example):

#include <ranges>

struct View : std::ranges::view_base 
  explicit View(const View&); // explicit copy constructor
  View& operator=(const View&);
  int* begin();
  int* end();

int main() 
  View v;
  auto r = std::views::take(v, 5); // hard error
Date User Action Args
2023-03-22 22:40:39adminsetmessages: + msg13481
2023-03-04 11:43:33adminsetmessages: + msg13440
2023-02-27 00:00:00admincreate