This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

3985. ranges::to should Mandates C not to be view

Section: 25.5.7.2 [range.utility.conv.to], 25.5.7.3 [range.utility.conv.adaptors] Status: New Submitter: Hewill Kang Opened: 2023-08-25 Last modified: 2023-10-30

Priority: 3

View other active issues in [range.utility.conv.to].

View all other issues in [range.utility.conv.to].

View all issues with New status.

Discussion:

In order to solve issues in LWG 3787(i) and LWG 3847(i) that the template parameter C can be specified as an unreasonable type, ranges::to adds a Mandates that requires C to be a cv-unqualified class type.

However, the earliest requirement that C not be a view was still imposed by the constraints of function signatures, although it is unclear why Constraints were used in the first place, such a way of kicking out the function candidate does bring undesirable hard errors and poor diagnostics (demo):

#include <ranges>

int main() {
  auto iota = std::views::iota(0, 10);
  auto take = std::ranges::to<std::ranges::take_view>(iota, 5);  // hard error in function body
  auto drop = iota | std::ranges::to<std::ranges::drop_view>(5); // poor diagnostics
}

I think consistent use of Mandates for template parameter C is more appropriate, as static_assert provide clearer and more readable diagnostics.

[2023-10-30; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4958.

  1. Modify 25.2 [ranges.syn] as indicated:

    #include <compare>              // see 17.11.1 [compare.syn]
    #include <initializer_list>     // see 17.10.2 [initializer.list.syn]
    #include <iterator>             // see 24.2 [iterator.synopsis]
    
    namespace std::ranges {
      […]
      // 25.5.7 [range.utility.conv], range conversions
      template<class C, input_range R, class... Args> requires (!view<C>)
        constexpr C to(R&& r, Args&&... args);                                          // freestanding
      template<template<class...> class C, input_range R, class... Args>
        constexpr auto to(R&& r, Args&&... args);                                       // freestanding
      template<class C, class... Args> requires (!view<C>)
        constexpr auto to(Args&&... args);                                              // freestanding
      template<template<class...> class C, class... Args>
        constexpr auto to(Args&&... args);                                              // freestanding
      […]
    }
    
  2. Modify 25.5.7.2 [range.utility.conv.to] as indicated:

    template<class C, input_range R, class... Args> requires (!view<C>)
      constexpr C to(R&& r, Args&&... args);
    

    -1- Mandates: C is a cv-unqualified class type and does not satisfy view.

    […]
  3. Modify 25.5.7.3 [range.utility.conv.adaptors] as indicated:

    template<class C, class... Args> requires (!view<C>)
      constexpr auto to(Args&&... args);
    template<template<class...> class C, class... Args>
      constexpr auto to(Args&&... args);
    

    -1- Mandates: For the first overload, C is a cv-unqualified class type and does not satisfy view.

    […]