ericniebler/stl2

LWG3280 and range adaptors

JohelEGP opened this issue · 2 comments

It has come to my attention that, given the resolution to http://wg21.link/LWG3280, the adaptors in the standard, which are specified as views::X(r, args) being equivalent to X_view{r, args} will no longer pass their range and potentially not view argument r through views::all. As part of the resolution, shouldn't the spec say that views::X(r, args) is equivalent to X_view{views::all(r), args}?

Let's use views::drop as representative of range adaptors, and assume the expression E is an lvalue range whose cv-unqualified type T does not model view. Per [range.drop.adaptor], views::drop{E, F} is equivalent to drop_view{E, F}. CTAD selects the explicit deduction guide:

template<class R>
  drop_view(R&&, range_difference_t<R>) -> drop_view<all_view<R>>;

since the constraints on the implicit guide derived from the drop_view(V, range_difference_t<V>) constructor are not satisfied (drop_view<V> requires view<V> ). Since T doesn't satisfy view, all_view<R> is decltype(ref_view{E}) per [range.all]/2.2). ref_view as a single explicit deduction guide:

template<class R>
  ref_view(R&) -> ref_view<R>;

and no (useful) implicit guides, so decltype(ref_view{E}) is ref_view<remove_reference_t<decltype((E))>>. Consequently views::drop(E, F) is equivalent to drop_view<ref_view<remove_reference_t<decltype((E))>>>{E, F}. Since E is implicitly convertible to ref_view<remove_reference_t<decltype((E))>> via ref_view's converting constructor, the initialization of drop_view<ref_view<remove_reference_t<decltype((E))>>>{E, F} invokes drop_view's (V, range_difference_t<V>) constructor as intended.

Is that clear enough? Is there a hole in the above reasoning?

Thank you. I had forgotten about the deduction guides.