Skip to content

Commit

Permalink
[libc++][ranges] LWG3984: ranges::to's recursion branch may be ill-fo…
Browse files Browse the repository at this point in the history
…rmed (llvm#87964)

This pull request implements LWG3984: ranges::to's recursion branch
may be ill-formed.

In the current implementation, ranges::to's recursion branch pipes the
range into a `views::transform(/* lambda */)`, which is a __range_adaptor_closure
object. In libc++, the pipe operator of __range_adaptor_closure requires a
viewable_range, so the following code won't compile, as the type of lvalue
`r` doesn't model viewable_range:

  #include <ranges>
  #include <vector>
  #include <list>

  int main() {
    std::vector<std::vector<int>> v;
    auto r = std::views::all(std::move(v));
    auto l = std::ranges::to<std::list<std::list<int>>>(r);
  }

Co-authored-by: A. Jiang <[email protected]>
  • Loading branch information
xiaoyang-sde and frederick-vs-ja authored Apr 26, 2024
1 parent 1728a56 commit e74be35
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 2 deletions.
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"`3919 <https://wg21.link/LWG3919>`__","``enumerate_view`` may invoke UB for sized common non-forward underlying ranges","Tokyo March 2024","","","|ranges|"
"`3950 <https://wg21.link/LWG3950>`__","``std::basic_string_view`` comparison operators are overspecified","Tokyo March 2024","|Complete|","18.0",""
"`3975 <https://wg21.link/LWG3975>`__","Specializations of ``basic_format_context`` should not be permitted","Tokyo March 2024","|Nothing To Do|","","|format|"
"`3984 <https://wg21.link/LWG3984>`__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","","","|ranges|"
"`3984 <https://wg21.link/LWG3984>`__","``ranges::to``'s recursion branch may be ill-formed","Tokyo March 2024","|Complete|","19.0","|ranges|"
"`4011 <https://wg21.link/LWG4011>`__","``""Effects: Equivalent to return""`` in ``[span.elem]``","Tokyo March 2024","|Nothing To Do|","",""
"`4012 <https://wg21.link/LWG4012>`__","``common_view::begin/end`` are missing the ``simple-view`` check","Tokyo March 2024","","","|ranges|"
"`4013 <https://wg21.link/LWG4013>`__","``lazy_split_view::outer-iterator::value_type`` should not provide default constructor","Tokyo March 2024","","","|ranges|"
Expand Down
3 changes: 2 additions & 1 deletion libcxx/include/__ranges/to.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <__ranges/concepts.h>
#include <__ranges/from_range.h>
#include <__ranges/range_adaptor.h>
#include <__ranges/ref_view.h>
#include <__ranges/size.h>
#include <__ranges/transform_view.h>
#include <__type_traits/add_pointer.h>
Expand Down Expand Up @@ -129,7 +130,7 @@ template <class _Container, input_range _Range, class... _Args>
// Try the recursive case.
} else if constexpr (input_range<range_reference_t<_Range>>) {
return ranges::to<_Container>(
__range | views::transform([](auto&& __elem) {
ref_view(__range) | views::transform([](auto&& __elem) {
return ranges::to<range_value_t<_Container>>(std::forward<decltype(__elem)>(__elem));
}),
std::forward<_Args>(__args)...);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,11 @@ constexpr void test_recursive() {
}

assert((in | std::ranges::to<C4>()) == result);

// LWG3984: ranges::to's recursion branch may be ill-formed
auto in_owning_view = std::views::all(std::move(in));
static_assert(!std::ranges::viewable_range<decltype((in_owning_view))>);
assert(std::ranges::to<C4>(in_owning_view) == result);
}

constexpr bool test() {
Expand Down

0 comments on commit e74be35

Please sign in to comment.