Currently, the template parameter C of ranges::to<C>(r) cannot be a view, which means we cannot write the following:

   string s;
   auto sv = ranges::to<string_view>(s); // error, string_view is view

I find this to be very inconvenient, as such limitation really prohibits a lot of useful use cases:

  string_view s = "1.2.3.4";
  auto r = s | views::split('.')
                  | views::transform(ranges::to<std::string_view>()); // error

Above, I tried to convert split substrings into string_views, but since ranges::to<string_view> is ill-formed, I can only use a verbose lambda such as views::transform([](auto r) { return std::string_view(r); ), which is unsatisfactory.

Not to mention collecting these into vector<string_view>, since ranges::to will first recursively construct the string_view element through ranges::to<string_view>, and again,  constraints not satisfied:

  std::string str = "1.2.3.4"
  auto result = str | views::split('.') | ranges::to<vector<string_view>>(); // error

The above cases are all reasonable use cases IMO. I guess that the constraint of "C should NOT be view" intends to prevent dangling pointers or to prevent users from making views in this way (as the range adaptor can do a better job?).

However, for the dangling issue, this is not a big deal. If ranges::to<C>(r) constructs C via C(std::forward<R>(r)), this will not be dangling even if C is a view, because constructors/CTAD of view classes already have appropriate constraints to prevent dangling, such as requiring R to be a viewable_range or borrowed_range.

The only possibility of danling is to construct C through C(ranges::begin(r), ranges::end(r). For example, when the rvalue string is passed, srtring_view can still be constructed in this way and resulting in dangling. But this is easy to solve, I believe we can just constrain R to satisfy borrowed_range, so we don't need to worry about the iterator's lifetime.

As for the second concern, I don't think any user would want to use ranges::to<ranges::take_view>(v, n) to make a take_view instead of views::take(5), but even if they did, it wouldn't cause much harm.

Furthermore, this constraint does not prevent ranges::to<gsl::span> or ranges::to<ranges::v3::meow_view> since third-party view-like classes do not satisfy the standard view concept.

In summary, removing this constraint seems reasonable and worthwhile to me. What do you think? Or is there something else I haven't considered that makes such constraint necessary?

Hewill