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.

4018. ranges::to's copy branch is underconstrained

Section: 26.5.7.2 [range.utility.conv.to] Status: New Submitter: Hewill Kang Opened: 2023-11-25 Last modified: 2023-11-25

Priority: Not Prioritized

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:

Unlike other branches that return a prvalue C, this branch's C is returned by elidable move, indicating that C needs to be move constructible (demo):

#include <ranges>
#include <vector>

struct nonmovable {
  nonmovable() = default;
  nonmovable(const nonmovable&) = delete;
  nonmovable& operator=(const nonmovable&) = delete;
};

template<class T>
struct nonmovable_vector : std::vector<T>, nonmovable { };

int main() {
  int arr[] = {42};
  auto v = std::ranges::to<nonmovable_vector<int>>(arr); // hard error
}

Proposed resolution:

This wording is relative to N4964.

  1. Modify 26.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.

    -2- Returns: An object of type C constructed from the elements of r in the following manner:

    1. (2.1) — If C does not satisfy input_range or convertible_to<range_reference_t<R>, range_value_t<C>> is true:

      1. (2.1.1) — […]

      2. (2.1.2) — […]

      3. (2.1.3) — […]

      4. (2.1.4) — Otherwise, if

        1. (2.1.4.?) — move_constructible<C> is true,

        2. (2.1.4.1) — constructible_from<C, Args...> is true, and

        3. (2.1.4.2) — container-insertable<C, range_reference_t<R>> is true:

          C c(std::forward<Args>(args)...);
          if constexpr (sized_range<R> && reservable-container<C>)
            c.reserve(static_cast<range_size_t<C>>(ranges::size(r)));
          ranges::copy(r, container-inserter<range_reference_t<R>>(c));
          
      5. (2.1.5) — Otherwise, the program is ill-formed.

    2. (2.2) — […]

    3. (2.3) — Otherwise, the program is ill-formed.