Skip to content

Commit f78d23d

Browse files
committed
[libc++][ranges] P3137R3: views::to_input
Implements: https://wg21.link/P3137R3 Closes #127873 https://wg21.link/range.to.input
1 parent c04b98f commit f78d23d

File tree

24 files changed

+1139
-2
lines changed

24 files changed

+1139
-2
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ Status
488488
---------------------------------------------------------- -----------------
489489
``__cpp_lib_ranges_concat`` *unimplemented*
490490
---------------------------------------------------------- -----------------
491+
``__cpp_lib_ranges_to_input`` ``202502L``
492+
---------------------------------------------------------- -----------------
491493
``__cpp_lib_ratio`` ``202306L``
492494
---------------------------------------------------------- -----------------
493495
``__cpp_lib_rcu`` *unimplemented*

libcxx/docs/ReleaseNotes/22.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Implemented Papers
4040

4141
- P2321R2: ``zip`` (`Github <https://llvm.org/PR105169>`__) (The paper is partially implemented. ``zip_transform_view``
4242
is implemented in this release)
43+
- P3137R3: ``views::to_input`` (`Github <https://llvm.org/PR127873>`__)
4344
- P3168R2: Give ``std::optional`` Range Support (`Github <https://llvm.org/PR105430>`__)
4445

4546
Improvements and New Features

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
"`P2900R14 <https://wg21.link/P2900R14>`__","Contracts for C++","2025-02 (Hagenberg)","","","`#127870 <https://github.com/llvm/llvm-project/issues/127870>`__",""
102102
"`P3475R2 <https://wg21.link/P3475R2>`__","Defang and deprecate ``memory_order::consume``","2025-02 (Hagenberg)","","","`#127871 <https://github.com/llvm/llvm-project/issues/127871>`__",""
103103
"`P2786R13 <https://wg21.link/P2786R13>`__","Trivial Relocatability For C++26","2025-02 (Hagenberg)","","","`#127872 <https://github.com/llvm/llvm-project/issues/127872>`__",""
104-
"`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","","","`#127873 <https://github.com/llvm/llvm-project/issues/127873>`__",""
104+
"`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","|Complete|","22","`#127873 <https://github.com/llvm/llvm-project/issues/127873>`__",""
105105
"`P0472R3 <https://wg21.link/P0472R3>`__","Put ``std::monostate`` in ``<utility>``","2025-02 (Hagenberg)","|Complete|","21","`#127874 <https://github.com/llvm/llvm-project/issues/127874>`__",""
106106
"`P3349R1 <https://wg21.link/P3349R1>`__","Converting contiguous iterators to pointers","2025-02 (Hagenberg)","","","`#127875 <https://github.com/llvm/llvm-project/issues/127875>`__",""
107107
"`P3372R3 <https://wg21.link/P3372R3>`__","constexpr containers and adaptors","2025-02 (Hagenberg)","|In Progress|","","`#127876 <https://github.com/llvm/llvm-project/issues/127876>`__",""

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ set(files
734734
__ranges/take_view.h
735735
__ranges/take_while_view.h
736736
__ranges/to.h
737+
__ranges/to_input_view.h
737738
__ranges/transform_view.h
738739
__ranges/view_interface.h
739740
__ranges/views.h
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___RANGES_TO_INPUT_VIEW_H
11+
#define _LIBCPP___RANGES_TO_INPUT_VIEW_H
12+
13+
#include <__concepts/constructible.h>
14+
#include <__concepts/convertible_to.h>
15+
#include <__config>
16+
#include <__iterator/concepts.h>
17+
#include <__iterator/iter_move.h>
18+
#include <__iterator/iter_swap.h>
19+
#include <__iterator/iterator_traits.h>
20+
#include <__ranges/access.h>
21+
#include <__ranges/all.h>
22+
#include <__ranges/concepts.h>
23+
#include <__ranges/enable_borrowed_range.h>
24+
#include <__ranges/range_adaptor.h>
25+
#include <__ranges/size.h>
26+
#include <__ranges/view_interface.h>
27+
#include <__type_traits/maybe_const.h>
28+
#include <__utility/forward.h>
29+
#include <__utility/move.h>
30+
31+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
32+
# pragma GCC system_header
33+
#endif
34+
35+
_LIBCPP_PUSH_MACROS
36+
#include <__undef_macros>
37+
38+
_LIBCPP_BEGIN_NAMESPACE_STD
39+
40+
#if _LIBCPP_STD_VER >= 26
41+
42+
namespace ranges {
43+
44+
// [range.to.input.view
45+
46+
template <input_range _View>
47+
requires view<_View>
48+
class to_input_view : public view_interface<to_input_view<_View>> {
49+
_View __base_ = _View(); // exposition only
50+
51+
// [range.to.input.iterator], class template to_input_view::iterator
52+
template <bool _Const>
53+
class iterator; // exposition only
54+
55+
public:
56+
_LIBCPP_HIDE_FROM_ABI to_input_view()
57+
requires default_initializable<_View>
58+
= default;
59+
_LIBCPP_HIDE_FROM_ABI constexpr explicit to_input_view(_View __base) : __base_(std::move(__base)) {}
60+
61+
_LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
62+
requires copy_constructible<_View>
63+
{
64+
return __base_;
65+
}
66+
_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
67+
68+
_LIBCPP_HIDE_FROM_ABI constexpr auto begin()
69+
requires(!__simple_view<_View>)
70+
{
71+
return iterator<false>{ranges::begin(__base_)};
72+
}
73+
_LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
74+
requires range<const _View>
75+
{
76+
return iterator<true>{ranges::begin(__base_)};
77+
}
78+
79+
_LIBCPP_HIDE_FROM_ABI constexpr auto end()
80+
requires(!__simple_view<_View>)
81+
{
82+
return ranges::end(__base_);
83+
}
84+
_LIBCPP_HIDE_FROM_ABI constexpr auto end() const
85+
requires range<const _View>
86+
{
87+
return ranges::end(__base_);
88+
}
89+
_LIBCPP_HIDE_FROM_ABI constexpr auto size()
90+
requires sized_range<_View>
91+
{
92+
return ranges::size(__base_);
93+
}
94+
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
95+
requires sized_range<const _View>
96+
{
97+
return ranges::size(__base_);
98+
}
99+
100+
// TODO: Implement when P2846R6 is available.
101+
// constexpr auto reserve_hint()
102+
// requires approximately_sized_range<_View>
103+
// {
104+
// return ranges::reserve_hint(__base_);
105+
// }
106+
// constexpr auto reserve_hint() const
107+
// requires approximately_sized_range<const _View>
108+
// {
109+
// return ranges::reserve_hint(__base_);
110+
// }
111+
};
112+
113+
template <class _Range>
114+
to_input_view(_Range&&) -> to_input_view<views::all_t<_Range>>;
115+
116+
// [range.to.input.iterator]
117+
118+
template <input_range _View>
119+
requires view<_View>
120+
template <bool _Const>
121+
class to_input_view<_View>::iterator {
122+
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>; // exposition only
123+
124+
iterator_t<_Base> __current_ = iterator_t<_Base>(); // exposition only
125+
126+
_LIBCPP_HIDE_FROM_ABI constexpr explicit iterator(iterator_t<_Base> __current)
127+
: __current_(std::move(__current)) {} // exposition only
128+
129+
friend class to_input_view<_View>;
130+
131+
public:
132+
using difference_type = range_difference_t<_Base>;
133+
using value_type = range_value_t<_Base>;
134+
using iterator_concept = input_iterator_tag;
135+
136+
_LIBCPP_HIDE_FROM_ABI iterator()
137+
requires default_initializable<iterator_t<_Base>>
138+
= default;
139+
140+
_LIBCPP_HIDE_FROM_ABI iterator(iterator&&) = default;
141+
_LIBCPP_HIDE_FROM_ABI iterator& operator=(iterator&&) = default;
142+
143+
_LIBCPP_HIDE_FROM_ABI constexpr iterator(iterator<!_Const> __i)
144+
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
145+
: __current_(std::move(__i.__current_)) {}
146+
147+
_LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); }
148+
_LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; }
149+
150+
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__current_; }
151+
152+
_LIBCPP_HIDE_FROM_ABI constexpr iterator& operator++() {
153+
++__current_;
154+
return *this;
155+
}
156+
_LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
157+
158+
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator& __x, const sentinel_t<_Base>& __y) {
159+
return __x.__current_ == __y;
160+
}
161+
162+
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const sentinel_t<_Base>& __y, const iterator& __x)
163+
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
164+
{
165+
return __y - __x.__current_;
166+
}
167+
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const iterator& __x, const sentinel_t<_Base>& __y)
168+
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
169+
{
170+
return __x.__current_ - __y;
171+
}
172+
173+
_LIBCPP_HIDE_FROM_ABI friend constexpr range_rvalue_reference_t<_Base> _LIBCPP_HIDE_FROM_ABI
174+
iter_move(const iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) {
175+
return ranges::iter_move(__i.__current_);
176+
}
177+
178+
_LIBCPP_HIDE_FROM_ABI friend constexpr void
179+
iter_swap(const iterator& __x,
180+
const iterator& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_)))
181+
requires indirectly_swappable<iterator_t<_Base>>
182+
{
183+
ranges::iter_swap(__x.__current_, __y.__current_);
184+
}
185+
};
186+
187+
template <class _View>
188+
constexpr bool enable_borrowed_range<to_input_view<_View>> = enable_borrowed_range<_View>;
189+
190+
namespace views {
191+
namespace __to_input_view {
192+
193+
struct __fn : __range_adaptor_closure<__fn> {
194+
template <class _Range>
195+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
196+
operator()(_Range&& __range) noexcept(noexcept(/**/ to_input_view(std::forward<_Range>(__range))))
197+
-> decltype(/*--*/ to_input_view(std::forward<_Range>(__range))) {
198+
return /*---------*/ to_input_view(std::forward<_Range>(__range));
199+
}
200+
201+
template <class _Range>
202+
requires(!common_range<_Range> && !forward_range<_Range>)
203+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
204+
operator()(_Range&& __range) noexcept(noexcept(views::all(std::forward<_Range>(__range))))
205+
-> decltype(/*--------------------------*/ views::all(std::forward<_Range>(__range))) {
206+
return /*---------------------------------*/ views::all(std::forward<_Range>(__range));
207+
}
208+
};
209+
210+
} // namespace __to_input_view
211+
212+
inline namespace __cpo {
213+
inline constexpr auto to_input = __to_input_view::__fn{};
214+
} // namespace __cpo
215+
} // namespace views
216+
} // namespace ranges
217+
218+
#endif // _LIBCPP_STD_VER >= 26
219+
220+
_LIBCPP_END_NAMESPACE_STD
221+
222+
_LIBCPP_POP_MACROS
223+
224+
#endif // _LIBCPP___RANGES_TO_INPUT_VIEW_H

libcxx/include/module.modulemap.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,9 @@ module std [system] {
19291929
header "__ranges/to.h"
19301930
export std.functional.bind_back
19311931
}
1932+
module to_input_view {
1933+
header "__ranges/to_input_view.h"
1934+
}
19321935
module transform_view {
19331936
header "__ranges/transform_view.h"
19341937
export std.functional.bind_back

libcxx/include/ranges

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,17 @@ namespace std::ranges {
362362
class chunk_by_view; // C++23
363363
364364
namespace views { inline constexpr unspecified chunk_by = unspecified; } // C++23
365+
366+
// [range.to.input], to input view
367+
template<input_range V>
368+
requires view<V>
369+
class to_input_view; // C++26
370+
371+
template<class V>
372+
constexpr bool enable_borrowed_range<to_input_view<V>> =
373+
enable_borrowed_range<V>; // C++26
374+
375+
namespace views { inline constexpr unspecified to_input = unspecified; } // C++26
365376
}
366377
367378
namespace std {
@@ -453,6 +464,10 @@ namespace std {
453464
# include <__ranges/zip_view.h>
454465
# endif
455466

467+
# if _LIBCPP_STD_VER >= 26
468+
# include <__ranges/to_input_view.h>
469+
# endif
470+
456471
# include <version>
457472

458473
// standard-mandated includes

libcxx/include/version

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ __cpp_lib_ranges_repeat 202207L <ranges>
211211
__cpp_lib_ranges_slide 202202L <ranges>
212212
__cpp_lib_ranges_starts_ends_with 202106L <algorithm>
213213
__cpp_lib_ranges_to_container 202202L <ranges>
214+
__cpp_lib_ranges_to_input 202502L <ranges>
214215
__cpp_lib_ranges_zip 202110L <ranges> <tuple> <utility>
215216
__cpp_lib_ratio 202306L <ratio>
216217
__cpp_lib_raw_memory_algorithms 201606L <memory>
@@ -590,6 +591,7 @@ __cpp_lib_void_t 201411L <type_traits>
590591
# define __cpp_lib_out_ptr 202311L
591592
// # define __cpp_lib_philox_engine 202406L
592593
// # define __cpp_lib_ranges_concat 202403L
594+
# define __cpp_lib_ranges_to_input 202502L
593595
# define __cpp_lib_ratio 202306L
594596
// # define __cpp_lib_rcu 202306L
595597
# define __cpp_lib_reference_wrapper 202403L

libcxx/modules/std/ranges.inc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,16 @@ export namespace std {
351351
using std::ranges::views::cartesian_product;
352352
}
353353
#endif
354+
355+
#if _LIBCPP_STD_VER >= 26
356+
// [range.to.input], to input view
357+
using std::ranges::to_input_view;
358+
359+
namespace views {
360+
using std::ranges::views::to_input;
361+
}
362+
#endif
363+
354364
} // namespace ranges
355365

356366
namespace views = ranges::views;

libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
# error "__cpp_lib_ranges_to_container should not be defined before c++23"
6565
# endif
6666

67+
# ifdef __cpp_lib_ranges_to_input
68+
# error "__cpp_lib_ranges_to_input should not be defined before c++26"
69+
# endif
70+
6771
# ifdef __cpp_lib_ranges_zip
6872
# error "__cpp_lib_ranges_zip should not be defined before c++23"
6973
# endif
@@ -114,6 +118,10 @@
114118
# error "__cpp_lib_ranges_to_container should not be defined before c++23"
115119
# endif
116120

121+
# ifdef __cpp_lib_ranges_to_input
122+
# error "__cpp_lib_ranges_to_input should not be defined before c++26"
123+
# endif
124+
117125
# ifdef __cpp_lib_ranges_zip
118126
# error "__cpp_lib_ranges_zip should not be defined before c++23"
119127
# endif
@@ -164,6 +172,10 @@
164172
# error "__cpp_lib_ranges_to_container should not be defined before c++23"
165173
# endif
166174

175+
# ifdef __cpp_lib_ranges_to_input
176+
# error "__cpp_lib_ranges_to_input should not be defined before c++26"
177+
# endif
178+
167179
# ifdef __cpp_lib_ranges_zip
168180
# error "__cpp_lib_ranges_zip should not be defined before c++23"
169181
# endif
@@ -217,6 +229,10 @@
217229
# error "__cpp_lib_ranges_to_container should not be defined before c++23"
218230
# endif
219231

232+
# ifdef __cpp_lib_ranges_to_input
233+
# error "__cpp_lib_ranges_to_input should not be defined before c++26"
234+
# endif
235+
220236
# ifdef __cpp_lib_ranges_zip
221237
# error "__cpp_lib_ranges_zip should not be defined before c++23"
222238
# endif
@@ -312,6 +328,10 @@
312328
# error "__cpp_lib_ranges_to_container should have the value 202202L in c++23"
313329
# endif
314330

331+
# ifdef __cpp_lib_ranges_to_input
332+
# error "__cpp_lib_ranges_to_input should not be defined before c++26"
333+
# endif
334+
315335
# if !defined(_LIBCPP_VERSION)
316336
# ifndef __cpp_lib_ranges_zip
317337
# error "__cpp_lib_ranges_zip should be defined in c++23"
@@ -434,6 +454,13 @@
434454
# error "__cpp_lib_ranges_to_container should have the value 202202L in c++26"
435455
# endif
436456

457+
# ifndef __cpp_lib_ranges_to_input
458+
# error "__cpp_lib_ranges_to_input should be defined in c++26"
459+
# endif
460+
# if __cpp_lib_ranges_to_input != 202502L
461+
# error "__cpp_lib_ranges_to_input should have the value 202502L in c++26"
462+
# endif
463+
437464
# if !defined(_LIBCPP_VERSION)
438465
# ifndef __cpp_lib_ranges_zip
439466
# error "__cpp_lib_ranges_zip should be defined in c++26"

0 commit comments

Comments
 (0)