[Bug c++/106669] New: incorrect definition of viewable_range ("more madness with move-only views")

h2+bugs at fsfe dot org gcc-bugzilla@gcc.gnu.org
Wed Aug 17 17:39:19 GMT 2022


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106669

            Bug ID: 106669
           Summary: incorrect definition of viewable_range ("more madness
                    with move-only views")
           Product: gcc
           Version: 12.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: h2+bugs at fsfe dot org
  Target Milestone: ---

In GCC12.1 we now have ranges that are views, but whose references aren't
viewable. See the code below.

Before views were allowed to be move-only, S was not considered a view, but `S
&` was considered viewable (it would just be wrapped in ref_view). Now, S is a
valid view, and S (no-ref!) is also a viewable range. But apparently the
requirements for viewable_range were not correctly updated, because `S &` is
now no longer viewable. The code in the standard is the following:

template<class T>
  concept viewable_­range =
    range<T> &&
    ((view<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>))));

For any `T &` where T is a view but not copy-constructible, this concept will
evaluate to false. I am assuming this is an LWG issue and will report on the
reflector unless you see a good reason for the current behaviour?


#include <string_view>
#include <ranges>

struct S : std::string_view, std::ranges::view_base
{
    S() = delete;
    S(S const &) = delete;
    S(S &&) = default;
    S & operator=(S const &) = delete;
    S & operator=(S &&) = default;

    S(std::string_view v) : std::string_view{v} {}
};

static_assert(std::ranges::view<S>);             // fails expectedly on
gcc11.3, passes on gcc12.1
static_assert(std::ranges::viewable_range<S>);   // fails expectedly on
gcc11.3, passes on gcc12.1
static_assert(std::ranges::viewable_range<S &>); // passes on gcc11.3, fails
unexpectedly on gcc12.1

int main()
{
    S s{"foo"};
    s | std::views::filter([] (char) { return true;}); // this fails in gcc12.1
}


More information about the Gcc-bugs mailing list