Skip to content

Commit 098426c

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

File tree

23 files changed

+956
-2
lines changed

23 files changed

+956
-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
@@ -39,6 +39,7 @@ Implemented Papers
3939
------------------
4040

4141
- P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release)
42+
- P3137R3: ``views::to_input`` (`Github <https://github.com/llvm/llvm-project/issues/127873>`__)
4243

4344
Improvements and New Features
4445
-----------------------------

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)","","",""
102102
"`P3475R2 <https://wg21.link/P3475R2>`__","Defang and deprecate ``memory_order::consume``","2025-02 (Hagenberg)","","",""
103103
"`P2786R13 <https://wg21.link/P2786R13>`__","Trivial Relocatability For C++26","2025-02 (Hagenberg)","","",""
104-
"`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","","",""
104+
"`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","|Complete|","22",""
105105
"`P0472R3 <https://wg21.link/P0472R3>`__","Put ``std::monostate`` in ``<utility>``","2025-02 (Hagenberg)","|Complete|","21",""
106106
"`P3349R1 <https://wg21.link/P3349R1>`__","Converting contiguous iterators to pointers","2025-02 (Hagenberg)","","",""
107107
"`P3372R3 <https://wg21.link/P3372R3>`__","constexpr containers and adaptors","2025-02 (Hagenberg)","|In Progress|","",""

libcxx/include/CMakeLists.txt

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

98102
// [range.empty], empty view
99103
using std::ranges::empty_view;

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)