Skip to content

Commit 57bb74c

Browse files
committed
[libcxx] P2278R4: cbegin and friends
Implements `basic_const_iterator` and the const accessors. Does not implement `const_view`
1 parent 2bc38dc commit 57bb74c

File tree

11 files changed

+609
-111
lines changed

11 files changed

+609
-111
lines changed

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"`P1899R3 <https://wg21.link/P1899R3>`__","LWG","``stride_view``","July 2022","","","|ranges|"
6262
"`P2093R14 <https://wg21.link/P2093R14>`__","LWG","Formatted output","July 2022","|Complete|","18.0","|format|"
6363
"`P2165R4 <https://wg21.link/P2165R4>`__","LWG","Compatibility between ``tuple``, ``pair`` and ``tuple-like`` objects","July 2022","",""
64-
"`P2278R4 <https://wg21.link/P2278R4>`__","LWG","``cbegin`` should always return a constant iterator","July 2022","","","|ranges|"
64+
"`P2278R4 <https://wg21.link/P2278R4>`__","LWG","``cbegin`` should always return a constant iterator","July 2022","In Progress","","|ranges|"
6565
"`P2286R8 <https://wg21.link/P2286R8>`__","LWG","Formatting Ranges","July 2022","|Complete|","16.0","|format| |ranges|"
6666
"`P2291R3 <https://wg21.link/P2291R3>`__","LWG","Add Constexpr Modifiers to Functions ``to_chars`` and ``from_chars`` for Integral Types in ``<charconv>`` Header","July 2022","|Complete|","16.0"
6767
"`P2302R4 <https://wg21.link/P2302R4>`__","LWG","``std::ranges::contains``","July 2022","|Complete|","19.0","|ranges|"

libcxx/include/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ set(files
444444
__iterator/bounded_iter.h
445445
__iterator/common_iterator.h
446446
__iterator/concepts.h
447+
__iterator/const_iterator.h
447448
__iterator/counted_iterator.h
448449
__iterator/cpp17_iterator_concepts.h
449450
__iterator/data.h
@@ -639,6 +640,7 @@ set(files
639640
__ranges/chunk_by_view.h
640641
__ranges/common_view.h
641642
__ranges/concepts.h
643+
__ranges/const_access.h
642644
__ranges/container_compatible_range.h
643645
__ranges/counted.h
644646
__ranges/dangling.h
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
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___ITERATOR_CONST_ITERATOR_H
11+
#define _LIBCPP___ITERATOR_CONST_ITERATOR_H
12+
13+
#include <__compare/three_way_comparable.h>
14+
#include <__concepts/common_with.h>
15+
#include <__concepts/different_from.h>
16+
#include <__iterator/concepts.h>
17+
#include <__iterator/iterator_traits.h>
18+
#include <__type_traits/common_reference.h>
19+
#include <__type_traits/common_type.h>
20+
#include <__type_traits/integral_constant.h>
21+
#include <__type_traits/is_specialization.h>
22+
23+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24+
# pragma GCC system_header
25+
#endif
26+
27+
_LIBCPP_PUSH_MACROS
28+
#include <__undef_macros>
29+
30+
_LIBCPP_BEGIN_NAMESPACE_STD
31+
32+
#if _LIBCPP_STD_VER >= 23
33+
34+
template <indirectly_readable _Iter>
35+
using iter_const_reference_t = common_reference_t<const iter_value_t<_Iter>&&, iter_reference_t<_Iter>>;
36+
37+
template <class _Iter>
38+
concept __constant_iterator = input_iterator<_Iter> && same_as<iter_const_reference_t<_Iter>, iter_reference_t<_Iter>>;
39+
40+
template <input_iterator _Iter>
41+
class basic_const_iterator;
42+
43+
template <input_iterator _Iter>
44+
using const_iterator = conditional_t<__constant_iterator<_Iter>, _Iter, basic_const_iterator<_Iter>>;
45+
template <semiregular _Sent>
46+
using const_sentinel = conditional_t<input_iterator<_Sent>, const_iterator<_Sent>, _Sent>;
47+
48+
template <class _Iter>
49+
concept __not_a_const_iterator = !__is_specialization_v<_Iter, basic_const_iterator>;
50+
51+
template <indirectly_readable _Iter>
52+
using __iter_const_rvalue_reference_t = common_reference_t<const iter_value_t<_Iter>&&, iter_rvalue_reference_t<_Iter>>;
53+
54+
template <class _Iter>
55+
struct __basic_const_iterator_concept {
56+
// clang-format off
57+
using iterator_concept =
58+
conditional_t<contiguous_iterator<_Iter>,
59+
contiguous_iterator_tag,
60+
conditional_t<random_access_iterator<_Iter>,
61+
random_access_iterator_tag,
62+
conditional_t<bidirectional_iterator<_Iter>,
63+
bidirectional_iterator_tag,
64+
conditional_t<forward_iterator<_Iter>,
65+
forward_iterator_tag,
66+
// else
67+
input_iterator_tag>>>>;
68+
// clang-format on
69+
};
70+
71+
template <class _Iter>
72+
struct __basic_const_iterator_category : __basic_const_iterator_concept<_Iter> {};
73+
template <forward_iterator _Iter>
74+
struct __basic_const_iterator_category<_Iter> : __basic_const_iterator_concept<_Iter> {
75+
using iterator_category = __basic_const_iterator_concept<_Iter>::iterator_concept;
76+
};
77+
78+
template <input_iterator _Iter>
79+
class _LIBCPP_TEMPLATE_VIS basic_const_iterator : __basic_const_iterator_category<_Iter> {
80+
_Iter __current = _Iter();
81+
82+
using __reference = iter_const_reference_t<_Iter>;
83+
using __rvalue_reference = __iter_const_rvalue_reference_t<_Iter>;
84+
85+
public:
86+
using value_type = iter_value_t<_Iter>;
87+
using difference_type = iter_difference_t<_Iter>;
88+
89+
_LIBCPP_HIDE_FROM_ABI basic_const_iterator()
90+
requires default_initializable<_Iter>
91+
= default;
92+
93+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator(_Iter __cur) : __current(std::move(__cur)) {}
94+
template <convertible_to<_Iter> _Type>
95+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator(basic_const_iterator<_Type> __cur)
96+
: __current(std::move(__cur.__current)) {}
97+
template <__different_from<basic_const_iterator> _Type>
98+
requires convertible_to<_Type, _Iter>
99+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator(_Type&& __cur) : __current(std::forward<_Type>(__cur)) {}
100+
101+
_LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const& noexcept { return __current; }
102+
_LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current); }
103+
104+
constexpr __reference operator*() const { return static_cast<__reference>(*__current); }
105+
_LIBCPP_HIDE_FROM_ABI constexpr const auto* operator->() const
106+
requires is_lvalue_reference_v<iter_reference_t<_Iter>> &&
107+
same_as<remove_cvref_t<iter_reference_t<_Iter>>, value_type>
108+
{
109+
if constexpr (contiguous_iterator<_Iter>) {
110+
return std::to_address(__current);
111+
} else {
112+
return std::addressof(*__current);
113+
}
114+
}
115+
116+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator& operator++() {
117+
++__current;
118+
return *this;
119+
}
120+
constexpr void operator++(int) { ++__current; }
121+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator operator++(int)
122+
requires forward_iterator<_Iter>
123+
{
124+
auto __tmp = *this;
125+
++__current;
126+
return __tmp;
127+
}
128+
129+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator& operator--()
130+
requires bidirectional_iterator<_Iter>
131+
{
132+
--__current;
133+
return *this;
134+
}
135+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator operator--(int)
136+
requires bidirectional_iterator<_Iter>
137+
{
138+
auto __tmp = *this;
139+
--__current;
140+
return __tmp;
141+
}
142+
143+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator& operator+=(difference_type __n)
144+
requires random_access_iterator<_Iter>
145+
{
146+
__current += __n;
147+
return *this;
148+
}
149+
_LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator& operator-=(difference_type __n)
150+
requires random_access_iterator<_Iter>
151+
{
152+
__current -= __n;
153+
return *this;
154+
}
155+
156+
_LIBCPP_HIDE_FROM_ABI constexpr __reference operator[](difference_type __n) const
157+
requires random_access_iterator<_Iter>
158+
{
159+
return static_cast<__reference>(__current[__n]);
160+
}
161+
162+
template <sentinel_for<_Iter> _Sent>
163+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Sent& __sent) const {
164+
return __current == __sent;
165+
}
166+
167+
template <__not_a_const_iterator _ConstIt>
168+
requires __constant_iterator<_ConstIt> && convertible_to<_Iter const&, _ConstIt>
169+
_LIBCPP_HIDE_FROM_ABI constexpr operator _ConstIt() const& {
170+
return __current;
171+
}
172+
template <__not_a_const_iterator _ConstIt>
173+
requires __constant_iterator<_ConstIt> && convertible_to<_Iter, _ConstIt>
174+
_LIBCPP_HIDE_FROM_ABI constexpr operator _ConstIt() && {
175+
return std::move(__current);
176+
}
177+
178+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const basic_const_iterator& __rhs) const
179+
requires random_access_iterator<_Iter>
180+
{
181+
return __current < __rhs.__current;
182+
}
183+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const basic_const_iterator& __rhs) const
184+
requires random_access_iterator<_Iter>
185+
{
186+
return __current > __rhs.__current;
187+
}
188+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const basic_const_iterator& __rhs) const
189+
requires random_access_iterator<_Iter>
190+
{
191+
return __current <= __rhs.__current;
192+
}
193+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const basic_const_iterator& __rhs) const
194+
requires random_access_iterator<_Iter>
195+
{
196+
return __current >= __rhs.__current;
197+
}
198+
_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const basic_const_iterator& __rhs) const
199+
requires random_access_iterator<_Iter> && three_way_comparable<_Iter>
200+
{
201+
return __current <=> __rhs.__current;
202+
}
203+
204+
template <__different_from<basic_const_iterator> _Iter2>
205+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Iter2& __rhs) const
206+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
207+
{
208+
return __current < __rhs.__current;
209+
}
210+
template <__different_from<basic_const_iterator> _Iter2>
211+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Iter2& __rhs) const
212+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
213+
{
214+
return __current > __rhs.__current;
215+
}
216+
template <__different_from<basic_const_iterator> _Iter2>
217+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Iter2& __rhs) const
218+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
219+
{
220+
return __current <= __rhs.__current;
221+
}
222+
template <__different_from<basic_const_iterator> _Iter2>
223+
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Iter2& __rhs) const
224+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
225+
{
226+
return __current >= __rhs.__current;
227+
}
228+
template <__different_from<basic_const_iterator> _Iter2>
229+
_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const _Iter2& __rhs) const
230+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2> &&
231+
three_way_comparable_with<_Iter, _Iter2>
232+
{
233+
return __current <=> __rhs.__current;
234+
}
235+
236+
template <__not_a_const_iterator _Iter2>
237+
friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Iter2& __lhs, const basic_const_iterator& __rhs)
238+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
239+
{
240+
return __lhs < __rhs.__current;
241+
}
242+
template <__not_a_const_iterator _Iter2>
243+
friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Iter2& __lhs, const basic_const_iterator& __rhs)
244+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
245+
{
246+
return __lhs > __rhs.__current;
247+
}
248+
template <__not_a_const_iterator _Iter2>
249+
friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Iter2& __lhs, const basic_const_iterator& __rhs)
250+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
251+
{
252+
return __lhs <= __rhs.__current;
253+
}
254+
template <__not_a_const_iterator _Iter2>
255+
friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Iter2& __lhs, const basic_const_iterator& __rhs)
256+
requires random_access_iterator<_Iter> && totally_ordered_with<_Iter, _Iter2>
257+
{
258+
return __lhs >= __rhs.__current;
259+
}
260+
261+
friend _LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator
262+
operator+(const basic_const_iterator& __it, difference_type __n)
263+
requires random_access_iterator<_Iter>
264+
{
265+
return basic_const_iterator(__it.__current + __n);
266+
}
267+
friend _LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator
268+
operator+(difference_type __n, const basic_const_iterator& __it)
269+
requires random_access_iterator<_Iter>
270+
{
271+
return basic_const_iterator(__it.__current + __n);
272+
}
273+
274+
friend _LIBCPP_HIDE_FROM_ABI constexpr basic_const_iterator
275+
operator-(const basic_const_iterator& __it, difference_type __n)
276+
requires random_access_iterator<_Iter>
277+
{
278+
return basic_const_iterator(__it.__current - __n);
279+
}
280+
template <sized_sentinel_for<_Iter> _Sent>
281+
_LIBCPP_HIDE_FROM_ABI constexpr difference_type operator-(const _Sent& __rhs) const {
282+
return __current - __rhs;
283+
}
284+
template <__not_a_const_iterator _Sent>
285+
requires sized_sentinel_for<_Sent, _Iter>
286+
friend _LIBCPP_HIDE_FROM_ABI constexpr difference_type
287+
operator-(const _Sent& __lhs, const basic_const_iterator& __rhs) {
288+
return __lhs - __rhs;
289+
}
290+
291+
friend _LIBCPP_HIDE_FROM_ABI constexpr __rvalue_reference iter_move(const basic_const_iterator& __it) noexcept(
292+
noexcept(static_cast<__rvalue_reference>(ranges::iter_move(__it.current_)))) {
293+
return static_cast<__rvalue_reference>(ranges::iter_move(__it.current_));
294+
}
295+
};
296+
297+
template <class _Type1, common_with<_Type1> _Type2>
298+
requires input_iterator<common_type_t<_Type1, _Type2>>
299+
struct common_type<basic_const_iterator<_Type1>, _Type2> {
300+
using type = basic_const_iterator<common_type_t<_Type1, _Type2>>;
301+
};
302+
template <class _Type1, common_with<_Type1> _Type2>
303+
requires input_iterator<common_type_t<_Type1, _Type2>>
304+
struct common_type<_Type2, basic_const_iterator<_Type1>> {
305+
using type = basic_const_iterator<common_type_t<_Type1, _Type2>>;
306+
};
307+
template <class _Type1, common_with<_Type1> _Type2>
308+
requires input_iterator<common_type_t<_Type1, _Type2>>
309+
struct common_type<basic_const_iterator<_Type1>, basic_const_iterator<_Type2>> {
310+
using type = basic_const_iterator<common_type_t<_Type1, _Type2>>;
311+
};
312+
313+
template <input_iterator _Iter>
314+
_LIBCPP_HIDE_FROM_ABI constexpr const_iterator<_Iter> make_const_iterator(_Iter __it) {
315+
return __it;
316+
}
317+
template <semiregular _Sent>
318+
_LIBCPP_HIDE_FROM_ABI constexpr const_sentinel<_Sent> make_const_sentinel(_Sent __sent) {
319+
return __sent;
320+
}
321+
322+
#endif // _LIBCPP_STD_VER >= 23
323+
324+
_LIBCPP_END_NAMESPACE_STD
325+
326+
_LIBCPP_POP_MACROS
327+
328+
#endif // _LIBCPP___ITERATOR_CONST_ITERATOR_H

0 commit comments

Comments
 (0)