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.

4381. std::ranges::to specification using CTAD not supported by core language

Section: 25.5.7.2 [range.utility.conv.to] Status: New Submitter: Jens Maurer Opened: 2025-09-23 Last modified: 2025-09-26

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:

25.5.7.2 [range.utility.conv.to] p4 defines a DEDUCE_EXPR that attempts CTAD (class template argument deduction) on a template template parameter C.

This is not supported by the core language; CWG 3003 will clarify the core wording accordingly.

Suggested resolution: Remove 25.5.7.2 [range.utility.conv.to] p3, p4, p5 and the respective entry in the synopsis as unimplementable.

Proposed resolution:

This wording is relative to N5014.

  1. Modify 25.2 [ranges.syn], header <ranges> synopsis, as indicated:

    […]
    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);
      template<template<class...> class C, input_range R, class... Args>
        constexpr auto to(R&& r, Args&&... args);
      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);  
      […]
    }
    
  2. Modify 25.5.7.2 [range.utility.conv.to] as indicated:

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

    -3- Let input-iterator be an exposition-only type:

    
    struct input-iterator { // exposition only
      using iterator_category = input_iterator_tag;
      using value_type = range_value_t<R>;
      using difference_type = ptrdiff_t;
      using pointer = add_pointer_t<range_reference_t<R>>;
      using reference = range_reference_t<R>;
      reference operator*() const;
      pointer operator->() const;
      input-iterator& operator++();
      input-iterator operator++(int);
      bool operator==(const input-iterator&) const;
    };
    

    [Note 1: input-iterator meets the syntactic requirements of Cpp17InputIterator. — end note]

    -4- Let DEDUCE_EXPR be defined as follows:

    1. (4.1) — C(declval<R>(), declval<Args>()...) if that is a valid expression,

    2. (4.2) — otherwise, C(from_range, declval<R>(), declval<Args>()...) if that is a valid expression,

    3. (4.3) — otherwise,

      
      C(declval<input-iterator>(), declval<input-iterator>(), declval<Args>()...)
      

      if that is a valid expression,

    4. (4.4) — otherwise, the program is ill-formed.

    -5- Returns: to<decltype(DEDUCE_EXPR)>(std::forward<R>(r), std::forward<Args>(args)...).