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 }