[libcxx-commits] [libcxx] [libcxx][c++26] P3137R3 views::to_input (PR #146396)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jul 8 02:07:12 PDT 2025


https://github.com/dywoq updated https://github.com/llvm/llvm-project/pull/146396

>From 03ec2ad766833c70aee79402957d26ea614f0d5b Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:18:33 +0300
Subject: [PATCH 01/14] [libcxx] add class to_input_view  to_input_view.h

---
 libcxx/.clangd                          |   2 +
 libcxx/include/__ranges/to_input_view.h | 100 ++++++++++++++++++++++++
 2 files changed, 102 insertions(+)
 create mode 100644 libcxx/.clangd
 create mode 100644 libcxx/include/__ranges/to_input_view.h

diff --git a/libcxx/.clangd b/libcxx/.clangd
new file mode 100644
index 0000000000000..8a80936175292
--- /dev/null
+++ b/libcxx/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+  Add: [--std=c++2c]
\ No newline at end of file
diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
new file mode 100644
index 0000000000000..eed017a9fadb0
--- /dev/null
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_TO_INPUT_VIEW_H
+#define _LIBCPP___RANGES_TO_INPUT_VIEW_H
+
+#include <__concepts/constructible.h>
+#include <__config>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/range_adaptor.h>
+#include <__ranges/view_interface.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+namespace ranges {
+
+template <input_range _V>
+  requires view<_V>
+class to_input_view : public view_interface<to_input_view<_V>> {
+private:
+  _V __base_;
+
+  template <bool _Cont>
+  class __iterator;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI to_input_view()
+    requires default_initializable<_V>
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit to_input_view(_V __base) : __base_(std::move(__base)) {}
+
+  // base
+  _LIBCPP_HIDE_FROM_ABI constexpr _V base() const&
+    requires copy_constructible<_V>
+  {
+    return __base_;
+  }
+  _LIBCPP_HIDE_FROM_ABI constexpr _V base() && { return std::move(__base_); }
+
+  // begin
+  _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+    requires(!__simple_view<_V>)
+  {
+    return __iterator<false>(ranges::begin(__base_));
+  }
+  _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+    requires range<const _V>
+  {
+    return __iterator<true>(ranges::begin(__base_));
+  }
+
+  // end
+  _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+    requires(!__simple_view<_V>)
+  {
+    return ranges::end(__base_);
+  }
+  _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+    requires range<const _V>
+  {
+    return ranges::end(__base_);
+  }
+
+  // size
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+    requires sized_range<_V>
+  {
+    return ranges::size(__base_);
+  }
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+    requires sized_range<const _V>
+  {
+    return ranges::size(__base_);
+  }
+};
+
+template <class _R>
+to_input_view(_R&&) -> to_input_view<ranges::views::all_t<_R>>;
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___RANGES_FROM_RANGE_H

>From ae6b1e3d894e63ddfbd67656c638b512cd6c1afa Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:45:09 +0300
Subject: [PATCH 02/14] [libcxx] implement to_input_view<_V>::__iterator class

---
 libcxx/include/__ranges/to_input_view.h | 76 ++++++++++++++++++++++++-
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index eed017a9fadb0..d7d38783585b2 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -10,12 +10,18 @@
 #ifndef _LIBCPP___RANGES_TO_INPUT_VIEW_H
 #define _LIBCPP___RANGES_TO_INPUT_VIEW_H
 
+#include <__algorithm/iter_swap.h>
 #include <__concepts/constructible.h>
 #include <__config>
+#include <__iterator/indirectly_comparable.h>
+#include <__iterator/iter_move.h>
+#include <__iterator/iter_swap.h>
+#include <__ranges/access.h>
 #include <__ranges/all.h>
 #include <__ranges/concepts.h>
 #include <__ranges/range_adaptor.h>
 #include <__ranges/view_interface.h>
+#include <__type_traits/maybe_const.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -91,10 +97,76 @@ class to_input_view : public view_interface<to_input_view<_V>> {
 template <class _R>
 to_input_view(_R&&) -> to_input_view<ranges::views::all_t<_R>>;
 
+template <input_range _V>
+  requires view<_V>
+template <bool _Const>
+class to_input_view<_V>::__iterator {
+  using _Base                  = __maybe_const<_Const, _V>;
+  iterator_t<_Base> __current_ = iterator_t<_Base>();
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
+
+public:
+  using difference_type  = range_difference_t<_Base>;
+  using value_type       = range_value_t<_Base>;
+  using iterator_concept = input_iterator_tag;
+
+  _LIBCPP_HIDE_FROM_ABI __iterator()
+    requires default_initializable<iterator_t<_Base>>
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&)            = default;
+  _LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
+    requires _Const && convertible_to<iterator_t<_V>, iterator_t<_Base>>
+      : __current_(std::move(__i.__current_)) {}
+
+  // base
+  _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&;
+  _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept;
+
+  // operator ++
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
+    ++__current_;
+    return *this;
+  }
+  _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
+
+  // operator==
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const sentinel_t<_Base>& __y) {
+    return __x.__current_ == __y;
+  }
+
+  // operator --
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const sentinel_t<_Base>& __y, const __iterator& __x)
+    requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
+  {
+    return __y - __x.__current_;
+  }
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const sentinel_t<_Base>& __y)
+    requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
+  {
+    return __x.__current_ - __y;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr range_rvalue_reference_t<_Base>
+  iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) {
+    return ranges::iter_move(__i.__current_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr void
+  iter_swap(const __iterator& __x, const __iterator& __y) noexcept(noexcept(iter_swap(__x.__current_, __y.__current_)))
+    requires indirectly_swappable<iterator_t<_Base>>
+  {
+    ranges::iter_swap(__x.__current_, __y.__current_);
+  }
+};
+
 } // namespace ranges
 
-#endif // _LIBCPP_STD_VER >= 23
+#endif // _LIBCPP_STD_VER >= 26
 
 _LIBCPP_END_NAMESPACE_STD
 
-#endif // _LIBCPP___RANGES_FROM_RANGE_H
+#endif // _LIBCPP___RANGES_TO_INPUT_VIEW_H

>From e9c0ff1d0786f3b475513ff19a1ad604d416659f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:45:35 +0300
Subject: [PATCH 03/14] [libcxx] implement adaptor for views::to_input

---
 libcxx/include/__ranges/to_input_view.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index d7d38783585b2..7fc526fc01f83 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -163,6 +163,25 @@ class to_input_view<_V>::__iterator {
   }
 };
 
+inline namespace __cpo {
+struct __to_input_range_adaptor {
+  template <ranges::input_range _V>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr auto operator()(_V&& __r) const {
+    return to_input_view<ranges::views::all_t<_V>>(std::forward<_V>(__r));
+  }
+
+  template <ranges::input_range _V>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend inline constexpr auto operator|(_V&& __r, __to_input_range_adaptor) {
+    return to_input_view<ranges::views::all_t<_V>>(std::forward<_V>(__r));
+  }
+};
+} // namespace __cpo
+
+namespace views {
+inline constexpr auto to_input = ranges::__cpo::__to_input_range_adaptor{};
+} // namespace views
+
+
 } // namespace ranges
 
 #endif // _LIBCPP_STD_VER >= 26

>From 7c98c8413534212d23aa2d65589e87c8f935b694 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:48:00 +0300
Subject: [PATCH 04/14] [libcxx] add [[nodiscard]] attributes in
 __ranges/to_input_view.h

---
 libcxx/include/__ranges/to_input_view.h | 34 +++++++++++++------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index 7fc526fc01f83..2d08c1b05c4f2 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -50,44 +50,44 @@ class to_input_view : public view_interface<to_input_view<_V>> {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit to_input_view(_V __base) : __base_(std::move(__base)) {}
 
   // base
-  _LIBCPP_HIDE_FROM_ABI constexpr _V base() const&
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _V base() const&
     requires copy_constructible<_V>
   {
     return __base_;
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr _V base() && { return std::move(__base_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _V base() && { return std::move(__base_); }
 
   // begin
-  _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
     requires(!__simple_view<_V>)
   {
     return __iterator<false>(ranges::begin(__base_));
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
     requires range<const _V>
   {
     return __iterator<true>(ranges::begin(__base_));
   }
 
   // end
-  _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end()
     requires(!__simple_view<_V>)
   {
     return ranges::end(__base_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
     requires range<const _V>
   {
     return ranges::end(__base_);
   }
 
   // size
-  _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
     requires sized_range<_V>
   {
     return ranges::size(__base_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
     requires sized_range<const _V>
   {
     return ranges::size(__base_);
@@ -123,34 +123,37 @@ class to_input_view<_V>::__iterator {
       : __current_(std::move(__i.__current_)) {}
 
   // base
-  _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&;
-  _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept;
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&;
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept;
 
   // operator ++
-  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
     ++__current_;
     return *this;
   }
   _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
 
   // operator==
-  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const sentinel_t<_Base>& __y) {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+  operator==(const __iterator& __x, const sentinel_t<_Base>& __y) {
     return __x.__current_ == __y;
   }
 
   // operator --
-  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const sentinel_t<_Base>& __y, const __iterator& __x)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+  operator-(const sentinel_t<_Base>& __y, const __iterator& __x)
     requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
   {
     return __y - __x.__current_;
   }
-  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const sentinel_t<_Base>& __y)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+  operator-(const __iterator& __x, const sentinel_t<_Base>& __y)
     requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
   {
     return __x.__current_ - __y;
   }
 
-  _LIBCPP_HIDE_FROM_ABI friend constexpr range_rvalue_reference_t<_Base>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_rvalue_reference_t<_Base>
   iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) {
     return ranges::iter_move(__i.__current_);
   }
@@ -181,7 +184,6 @@ namespace views {
 inline constexpr auto to_input = ranges::__cpo::__to_input_range_adaptor{};
 } // namespace views
 
-
 } // namespace ranges
 
 #endif // _LIBCPP_STD_VER >= 26

>From 1d1ebd6930180fa5a05c0278924669b52b03d771 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:50:09 +0300
Subject: [PATCH 05/14] [libcxx] implement base() method for
 to_input_view<_V>::__iterator in __ranges/to_input_view.h

---
 libcxx/include/__ranges/to_input_view.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index 2d08c1b05c4f2..470c7ee1179c0 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -123,8 +123,8 @@ class to_input_view<_V>::__iterator {
       : __current_(std::move(__i.__current_)) {}
 
   // base
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&;
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept;
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; }
 
   // operator ++
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {

>From d9fbb993ecd3b59678101d31e22eae5cf3237f6e Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 18:55:03 +0300
Subject: [PATCH 06/14] [libcxx] update synopsis and include
 __ranges/to_view_input.h in <ranges> header

---
 libcxx/include/ranges | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 2a6321bd2c5d8..d95e31f9c19ff 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -352,6 +352,19 @@ namespace std::ranges {
   class chunk_by_view;                                                      // C++23
 
   namespace views { inline constexpr unspecified chunk_by = unspecified; }  // C++23
+
+  // [range.to.input], to input view
+  template<input_range V>
+    requires view<V>
+  class to_input_view;
+
+  template<class V>
+  constexpr bool enable_borrowed_range<to_input_view<V>> =
+      enable_borrowed_range<V>;
+
+  namespace views {
+    inline constexpr unspecified to_input = unspecified;
+  }
 }
 
 namespace std {
@@ -442,6 +455,10 @@ namespace std {
 #    include <__ranges/zip_view.h>
 #  endif
 
+#  if _LIBCPP_STD_VER >= 26
+#    include <__ranges/to_input_view.h>
+#  endif
+
 #  include <version>
 
 // standard-mandated includes

>From b249a146086969701ee603f2aba2734279acd7fe Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 19:31:46 +0300
Subject: [PATCH 07/14] [libcxx] add feature test macro
 __cpp_lib_ranges_to_input

---
 libcxx/docs/FeatureTestMacroTable.rst         |  2 ++
 libcxx/include/__ranges/to_input_view.h       |  8 ++++--
 libcxx/include/version                        |  2 ++
 .../ranges.version.compile.pass.cpp           | 27 +++++++++++++++++++
 .../version.version.compile.pass.cpp          | 27 +++++++++++++++++++
 .../generate_feature_test_macro_components.py |  5 ++++
 6 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3c635e5e46bbd..09f2545657e3d 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -484,6 +484,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_ranges_concat``                                *unimplemented*
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_ranges_to_input``                              ``202502L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_ratio``                                        ``202306L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_rcu``                                          *unimplemented*
diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index 470c7ee1179c0..974a6204f4881 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -104,13 +104,13 @@ class to_input_view<_V>::__iterator {
   using _Base                  = __maybe_const<_Const, _V>;
   iterator_t<_Base> __current_ = iterator_t<_Base>();
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
-
 public:
   using difference_type  = range_difference_t<_Base>;
   using value_type       = range_value_t<_Base>;
   using iterator_concept = input_iterator_tag;
 
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
+
   _LIBCPP_HIDE_FROM_ABI __iterator()
     requires default_initializable<iterator_t<_Base>>
   = default;
@@ -126,6 +126,10 @@ class to_input_view<_V>::__iterator {
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); }
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; }
 
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const noexcept(noexcept(*__current_)) {
+    return *__current_;
+  }
+
   // operator ++
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
     ++__current_;
diff --git a/libcxx/include/version b/libcxx/include/version
index 91fe48351e161..7baf77417c0bb 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -209,6 +209,7 @@ __cpp_lib_ranges_repeat                                 202207L <ranges>
 __cpp_lib_ranges_slide                                  202202L <ranges>
 __cpp_lib_ranges_starts_ends_with                       202106L <algorithm>
 __cpp_lib_ranges_to_container                           202202L <ranges>
+__cpp_lib_ranges_to_input                               202502L <ranges>
 __cpp_lib_ranges_zip                                    202110L <ranges> <tuple> <utility>
 __cpp_lib_ratio                                         202306L <ratio>
 __cpp_lib_raw_memory_algorithms                         201606L <memory>
@@ -586,6 +587,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_out_ptr                              202311L
 // # define __cpp_lib_philox_engine                        202406L
 // # define __cpp_lib_ranges_concat                        202403L
+# define __cpp_lib_ranges_to_input                      202502L
 # define __cpp_lib_ratio                                202306L
 // # define __cpp_lib_rcu                                  202306L
 # define __cpp_lib_reference_wrapper                    202403L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index 4cf5178dd7b8f..faea63766f020 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -64,6 +64,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -114,6 +118,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -164,6 +172,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -217,6 +229,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -312,6 +328,10 @@
 #    error "__cpp_lib_ranges_to_container should have the value 202202L in c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  if !defined(_LIBCPP_VERSION)
 #    ifndef __cpp_lib_ranges_zip
 #      error "__cpp_lib_ranges_zip should be defined in c++23"
@@ -434,6 +454,13 @@
 #    error "__cpp_lib_ranges_to_container should have the value 202202L in c++26"
 #  endif
 
+#  ifndef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should be defined in c++26"
+#  endif
+#  if __cpp_lib_ranges_to_input != 202502L
+#    error "__cpp_lib_ranges_to_input should have the value 202502L in c++26"
+#  endif
+
 #  if !defined(_LIBCPP_VERSION)
 #    ifndef __cpp_lib_ranges_zip
 #      error "__cpp_lib_ranges_zip should be defined in c++26"
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index e546719142231..1a6ed20cdbeb2 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -680,6 +680,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -1612,6 +1616,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -2715,6 +2723,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -4085,6 +4097,10 @@
 #    error "__cpp_lib_ranges_to_container should not be defined before c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  ifdef __cpp_lib_ranges_zip
 #    error "__cpp_lib_ranges_zip should not be defined before c++23"
 #  endif
@@ -5674,6 +5690,10 @@
 #    error "__cpp_lib_ranges_to_container should have the value 202202L in c++23"
 #  endif
 
+#  ifdef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should not be defined before c++26"
+#  endif
+
 #  if !defined(_LIBCPP_VERSION)
 #    ifndef __cpp_lib_ranges_zip
 #      error "__cpp_lib_ranges_zip should be defined in c++23"
@@ -7584,6 +7604,13 @@
 #    error "__cpp_lib_ranges_to_container should have the value 202202L in c++26"
 #  endif
 
+#  ifndef __cpp_lib_ranges_to_input
+#    error "__cpp_lib_ranges_to_input should be defined in c++26"
+#  endif
+#  if __cpp_lib_ranges_to_input != 202502L
+#    error "__cpp_lib_ranges_to_input should have the value 202502L in c++26"
+#  endif
+
 #  if !defined(_LIBCPP_VERSION)
 #    ifndef __cpp_lib_ranges_zip
 #      error "__cpp_lib_ranges_zip should be defined in c++26"
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index edd7b124a1fb3..8455298d8b12c 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1137,6 +1137,11 @@ def add_version_header(tc):
             "values": {"c++23": 202202},
             "headers": ["ranges"],
         },
+		{
+            "name": "__cpp_lib_ranges_to_input",
+            "values": {"c++26":202502}, # P3137R3 views::to_input
+            "headers": ["ranges"]
+		},
         {
             "name": "__cpp_lib_ranges_zip",
             "values": {"c++23": 202110},

>From 4cb308111926bfbff5d29f508fd46a3aa396c462 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 19:35:47 +0300
Subject: [PATCH 08/14] [libcxx] add enable_borrowed_range to
 __ranges/to_input_view.h

---
 libcxx/include/__ranges/to_input_view.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/include/__ranges/to_input_view.h b/libcxx/include/__ranges/to_input_view.h
index 974a6204f4881..b770730386bb6 100644
--- a/libcxx/include/__ranges/to_input_view.h
+++ b/libcxx/include/__ranges/to_input_view.h
@@ -170,6 +170,9 @@ class to_input_view<_V>::__iterator {
   }
 };
 
+template <class _V>
+constexpr bool enable_borrowed_range<to_input_view<_V>> = enable_borrowed_range<_V>;
+
 inline namespace __cpo {
 struct __to_input_range_adaptor {
   template <ranges::input_range _V>

>From 4428225ef0f2c5215388f5b6b371b48bab95f10e Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 20:14:48 +0300
Subject: [PATCH 09/14] [libcxx] write tests for to_input

---
 .../range.to_input_view/test.pass.cpp         | 75 +++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
new file mode 100644
index 0000000000000..c6ae2b9a132a2
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+#include "../../../../support/assert_macros.h"
+#include <iterator>
+#include <memory>
+#include <ranges>
+#include <vector>
+
+int main() {
+  {
+    auto input_view = std::vector<int>{} | std::ranges::views::to_input;
+    TEST_REQUIRE(input_view.begin() == input_view.end(), "begin() == end() is false");
+  }
+
+  {
+    auto input_view = std::vector<int>{100, 200} | std::ranges::views::to_input;
+    auto it         = input_view.begin();
+    TEST_REQUIRE(*it == 100, "*it == 100 is false");
+    ++it;
+    TEST_REQUIRE(*it == 200, "*it == 200 is false");
+    ++it;
+    TEST_REQUIRE(it == input_view.end(), "it == input_view.end() is false");
+  }
+
+  {
+    auto input_view = std::vector<int>{1, 2, 3} | std::ranges::views::to_input;
+    auto base_vec   = input_view.base();
+    TEST_REQUIRE(base_vec.size() == 3, "base_vec.size() == 0 is false");
+    TEST_REQUIRE(base_vec[0] == 1, "base_vec[0] == 1 is false");
+  }
+
+  {
+    const std::vector<int> vec(5);
+    auto input_view = std::ranges::views::to_input(vec);
+    TEST_REQUIRE(input_view.size() == 5, "input_view.size() == 5 is false");
+  }
+
+  {
+    std::vector<std::unique_ptr<int>> vec;
+    vec.push_back(std::make_unique<int>(10));
+    vec.push_back(std::make_unique<int>(20));
+
+    auto input_view = std::ranges::views::to_input(std::move(vec));
+
+    auto it   = input_view.begin();
+    auto val1 = std::ranges::iter_move(it);
+    TEST_REQUIRE(*val1 == 10, "*val1 == 10 is false");
+    TEST_REQUIRE(it->get() == nullptr, "it->get() == nullptr is false");
+
+    ++it;
+    auto val2 = std::ranges::iter_move(it);
+    TEST_REQUIRE(*val2 == 20, "*val2 == 20 is false");
+    TEST_REQUIRE(it->get() == nullptr, "it->get() == nullptr is false");
+  }
+
+  {
+    std::vector<int> vec{1, 2};
+    auto input_view = std::ranges::views::to_input(vec);
+    auto it1        = input_view.begin();
+    auto it2        = std::next(it1);
+
+    std::ranges::iter_swap(it1, it2);
+
+    TEST_REQUIRE(vec[0] == 2, "vec[0] == 2 is false");
+    TEST_REQUIRE(vec[1] == 1, "vec[1] == 1 is false");
+  }
+}
\ No newline at end of file

>From 2e471248204c00581ba0c72b2f5440c19a01963b Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 20:15:50 +0300
Subject: [PATCH 10/14] [libcxx] change path to assert_macros.h header in
 to_input tests

---
 .../std/ranges/range.adaptors/range.to_input_view/test.pass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
index c6ae2b9a132a2..41cb73b5fa762 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
@@ -8,7 +8,7 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
 
-#include "../../../../support/assert_macros.h"
+#include "assert_macros.h"
 #include <iterator>
 #include <memory>
 #include <ranges>

>From ec53a77a80cb2cfe0c5ccdaf2f44a03a7e324f19 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Mon, 30 Jun 2025 20:19:53 +0300
Subject: [PATCH 11/14] [libcxx] remove .clangd

---
 libcxx/.clangd | 2 --
 1 file changed, 2 deletions(-)
 delete mode 100644 libcxx/.clangd

diff --git a/libcxx/.clangd b/libcxx/.clangd
deleted file mode 100644
index 8a80936175292..0000000000000
--- a/libcxx/.clangd
+++ /dev/null
@@ -1,2 +0,0 @@
-CompileFlags:
-  Add: [--std=c++2c]
\ No newline at end of file

>From 06aa001badce69c891436b00f186d353f4d62aa4 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Sun, 6 Jul 2025 19:51:44 +0300
Subject: [PATCH 12/14] [libcxx] add
 range.to_input_view.range_properties.compile.pass test

---
 .../range_properties.compile.pass.cpp         | 19 +++++
 .../range.to_input_view/test.pass.cpp         | 75 -------------------
 2 files changed, 19 insertions(+), 75 deletions(-)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.to_input_view/range_properties.compile.pass.cpp
 delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/range_properties.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/range_properties.compile.pass.cpp
new file mode 100644
index 0000000000000..837e3c545db19
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/range_properties.compile.pass.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: std-at-least-c++26
+
+#include <ranges>
+#include <vector>
+
+auto vec        = std::vector<int>{2, 3, 4};
+auto input_view = vec | std::ranges::views::to_input;
+static_assert(std::ranges::input_range<decltype(input_view)>);
+static_assert(std::ranges::view<decltype(input_view)>);
+static_assert(std::ranges::sized_range<decltype(input_view)>);
+static_assert(std::ranges::borrowed_range<decltype(input_view)>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
deleted file mode 100644
index 41cb73b5fa762..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/test.pass.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-
-#include "assert_macros.h"
-#include <iterator>
-#include <memory>
-#include <ranges>
-#include <vector>
-
-int main() {
-  {
-    auto input_view = std::vector<int>{} | std::ranges::views::to_input;
-    TEST_REQUIRE(input_view.begin() == input_view.end(), "begin() == end() is false");
-  }
-
-  {
-    auto input_view = std::vector<int>{100, 200} | std::ranges::views::to_input;
-    auto it         = input_view.begin();
-    TEST_REQUIRE(*it == 100, "*it == 100 is false");
-    ++it;
-    TEST_REQUIRE(*it == 200, "*it == 200 is false");
-    ++it;
-    TEST_REQUIRE(it == input_view.end(), "it == input_view.end() is false");
-  }
-
-  {
-    auto input_view = std::vector<int>{1, 2, 3} | std::ranges::views::to_input;
-    auto base_vec   = input_view.base();
-    TEST_REQUIRE(base_vec.size() == 3, "base_vec.size() == 0 is false");
-    TEST_REQUIRE(base_vec[0] == 1, "base_vec[0] == 1 is false");
-  }
-
-  {
-    const std::vector<int> vec(5);
-    auto input_view = std::ranges::views::to_input(vec);
-    TEST_REQUIRE(input_view.size() == 5, "input_view.size() == 5 is false");
-  }
-
-  {
-    std::vector<std::unique_ptr<int>> vec;
-    vec.push_back(std::make_unique<int>(10));
-    vec.push_back(std::make_unique<int>(20));
-
-    auto input_view = std::ranges::views::to_input(std::move(vec));
-
-    auto it   = input_view.begin();
-    auto val1 = std::ranges::iter_move(it);
-    TEST_REQUIRE(*val1 == 10, "*val1 == 10 is false");
-    TEST_REQUIRE(it->get() == nullptr, "it->get() == nullptr is false");
-
-    ++it;
-    auto val2 = std::ranges::iter_move(it);
-    TEST_REQUIRE(*val2 == 20, "*val2 == 20 is false");
-    TEST_REQUIRE(it->get() == nullptr, "it->get() == nullptr is false");
-  }
-
-  {
-    std::vector<int> vec{1, 2};
-    auto input_view = std::ranges::views::to_input(vec);
-    auto it1        = input_view.begin();
-    auto it2        = std::next(it1);
-
-    std::ranges::iter_swap(it1, it2);
-
-    TEST_REQUIRE(vec[0] == 2, "vec[0] == 2 is false");
-    TEST_REQUIRE(vec[1] == 1, "vec[1] == 1 is false");
-  }
-}
\ No newline at end of file

>From 5bdcefc3891d6798ce7d3a637d5fc9616c787b6f Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Sun, 6 Jul 2025 19:57:33 +0300
Subject: [PATCH 13/14] [libcxx] add range.to_input_view.empty_vec.compile.pass
 test

---
 .../empty_vec.compile.pass.cpp                  | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.to_input_view/empty_vec.compile.pass.cpp

diff --git a/libcxx/test/std/ranges/range.adaptors/range.to_input_view/empty_vec.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/empty_vec.compile.pass.cpp
new file mode 100644
index 0000000000000..677f3ba4a67ec
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.to_input_view/empty_vec.compile.pass.cpp
@@ -0,0 +1,17 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: std-at-least-c++26
+
+#include <ranges>
+#include <vector>
+
+std::vector<int> vec;
+auto input_view = vec | std::ranges::views::to_input;
+static_assert(input_view.begin() == input_view.end());
+static_assert(input_view.size() == 0);

>From bd4ff34f552272e8e0f142ad744f3eecd19f2978 Mon Sep 17 00:00:00 2001
From: dywoq <aleks.koyf at gmail.com>
Date: Tue, 8 Jul 2025 12:06:51 +0300
Subject: [PATCH 14/14] [libcxx] edit ranges.inc to include to_input_view

---
 libcxx/modules/std/ranges.inc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index adabeeb22d551..c699c6062bfeb 100644
--- a/libcxx/modules/std/ranges.inc
+++ b/libcxx/modules/std/ranges.inc
@@ -337,6 +337,15 @@ export namespace std {
     }
 #endif // _LIBCPP_STD_VER >= 23
 
+#if _LIBCPP_STD_VER >= 26
+	// [range.to.input], to input view
+	using std::ranges::to_input_view;
+
+	namespace views {
+	  using std::ranges::views::to_input;
+	}
+#endif // _LIBCPP_STD_VER >= 26
+
 #if 0
     // [range.stride], stride view
     using std::ranges::stride_view;



More information about the libcxx-commits mailing list