libstdc++: stl_iterator_base_funcs.h Source File

libstdc++

stl_iterator_base_funcs.h
Go to the documentation of this file.
1// Functions used by iterators -*- C++ -*-
2
3// Copyright (C) 2001-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996-1998
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_iterator_base_funcs.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{iterator}
54 *
55 * This file contains all of the general iterator-related utility
56 * functions, such as distance() and advance().
57 */
58
59#ifndef _STL_ITERATOR_BASE_FUNCS_H
60#define _STL_ITERATOR_BASE_FUNCS_H 1
61
62#ifdef _GLIBCXX_SYSHDR
63#pragma GCC system_header
64#endif
65
66#include <bits/concept_check.h>
67#include <debug/assertions.h>
68#include <bits/stl_iterator_base_types.h>
69#include <bits/move.h> // For _GLIBCXX_MOVE
70
71namespace std _GLIBCXX_VISIBILITY(default)
72{
73_GLIBCXX_BEGIN_NAMESPACE_VERSION
74
75_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
76 // Forward declaration for the overloads of __distance.
77 template <typename> struct _List_iterator;
78 template <typename> struct _List_const_iterator;
79_GLIBCXX_END_NAMESPACE_CONTAINER
80
81 template<typename _InputIterator>
82 inline _GLIBCXX14_CONSTEXPR
83 typename iterator_traits<_InputIterator>::difference_type
84 __distance(_InputIterator __first, _InputIterator __last,
85 input_iterator_tag)
86 {
87 // concept requirements
88 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
89
90 typename iterator_traits<_InputIterator>::difference_type __n = 0;
91 while (__first != __last)
92 {
93 ++__first;
94 ++__n;
95 }
96 return __n;
97 }
98
99 template<typename _RandomAccessIterator>
100 __attribute__((__always_inline__))
101 inline _GLIBCXX14_CONSTEXPR
102 typename iterator_traits<_RandomAccessIterator>::difference_type
103 __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
104 random_access_iterator_tag)
105 {
106 // concept requirements
107 __glibcxx_function_requires(_RandomAccessIteratorConcept<
108 _RandomAccessIterator>)
109 return __last - __first;
110 }
111
112#if _GLIBCXX_USE_CXX11_ABI
113 // Forward declaration because of the qualified call in distance.
114 template<typename _Tp>
115 ptrdiff_t
116 __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
117 _GLIBCXX_STD_C::_List_iterator<_Tp>,
118 input_iterator_tag);
119
120 template<typename _Tp>
121 ptrdiff_t
122 __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
123 _GLIBCXX_STD_C::_List_const_iterator<_Tp>,
124 input_iterator_tag);
125#endif
126
127#if __cplusplus >= 201103L
128 // Give better error if std::distance called with a non-Cpp17InputIterator.
129 template<typename _OutputIterator>
130 void
131 __distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete;
132#endif
133
134#ifdef __glibcxx_concepts
135/// @cond undocumented
136namespace __detail
137{
138
139 // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is
140 // at least as strong as ITER_TRAITS(Iter)::iterator_concept.
141 template<typename _Iter>
142 concept __iter_category_converts_to_concept
143 = convertible_to<typename __iter_traits<_Iter>::iterator_category,
144 typename __iter_traits<_Iter>::iterator_concept>;
145
146 // Satisfied if the type is a C++20 iterator that defines iterator_concept,
147 // and its iterator_concept is stronger than its iterator_category (if any).
148 // Used by std::distance and std::advance to detect iterators which should
149 // dispatch based on their C++20 concept not their C++17 category.
150 template<typename _Iter>
151 concept __promotable_iterator
152 = input_iterator<_Iter>
153 && requires { typename __iter_traits<_Iter>::iterator_concept; }
154 && ! __iter_category_converts_to_concept<_Iter>;
155
156} // namespace __detail
157/// @endcond
158#endif
159
160 /**
161 * @brief A generalization of pointer arithmetic.
162 * @param __first,__last Input iterators that form a valid range.
163 * @return The distance between them.
164 *
165 * Returns `n` such that `__first + n == __last`.
166 * This requires that `__last` must be reachable from `__first`, or
167 * for random access iterators either `__last` is reachable from `__first`
168 * or `__first` is reachable from `__last`. In the latter case, `n`
169 * may be negative.
170 *
171 * For random access iterators, this uses their `+` and `-` operations
172 * and is constant time. For other %iterator classes they are linear time.
173 */
174 template<typename _InputIterator>
175 _GLIBCXX_NODISCARD __attribute__((__always_inline__))
176 inline _GLIBCXX17_CONSTEXPR
177 typename iterator_traits<_InputIterator>::difference_type
178 distance(_InputIterator __first, _InputIterator __last)
179 {
180#ifdef __glibcxx_concepts
181 // A type which satisfies the C++20 random_access_iterator concept might
182 // have input_iterator_tag as its iterator_category type, which would
183 // mean we select the O(n) __distance. Or a C++20 std::input_iterator
184 // that is not a Cpp17InputIterator might have output_iterator_tag as
185 // its iterator_category type and then calling __distance with
186 // std::__iterator_category(__first) would be ill-formed.
187 // So for C++20 iterator types we can just choose to do the right thing.
188 if constexpr (__detail::__promotable_iterator<_InputIterator>)
189 {
190 if constexpr (random_access_iterator<_InputIterator>)
191 return __last - __first;
192 else
193 return std::__distance(std::move(__first), std::move(__last),
194 input_iterator_tag());
195 }
196 else // assume it meets the Cpp17InputIterator requirements:
197#endif
198 // concept requirements -- taken care of in __distance
199 return std::__distance(__first, __last,
200 std::__iterator_category(__first));
201 }
202
203 /// @cond undocumented
204
205 template<typename _InputIterator, typename _Distance>
206 inline _GLIBCXX14_CONSTEXPR void
207 __advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
208 {
209 // concept requirements
210 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
211 __glibcxx_assert(__n >= 0);
212 while (__n-- > 0)
213 ++__i;
214 }
215
216 template<typename _BidirectionalIterator, typename _Distance>
217 inline _GLIBCXX14_CONSTEXPR void
218 __advance(_BidirectionalIterator& __i, _Distance __n,
219 bidirectional_iterator_tag)
220 {
221 // concept requirements
222 __glibcxx_function_requires(_BidirectionalIteratorConcept<
223 _BidirectionalIterator>)
224 if (__n > 0)
225 while (__n--)
226 ++__i;
227 else
228 while (__n++)
229 --__i;
230 }
231
232 template<typename _RandomAccessIterator, typename _Distance>
233 inline _GLIBCXX14_CONSTEXPR void
234 __advance(_RandomAccessIterator& __i, _Distance __n,
235 random_access_iterator_tag)
236 {
237 // concept requirements
238 __glibcxx_function_requires(_RandomAccessIteratorConcept<
239 _RandomAccessIterator>)
240 if (__builtin_constant_p(__n) && __n == 1)
241 ++__i;
242 else if (__builtin_constant_p(__n) && __n == -1)
243 --__i;
244 else
245 __i += __n;
246 }
247
248#if __cplusplus >= 201103L
249 // Give better error if std::advance called with a non-Cpp17InputIterator.
250 template<typename _OutputIterator, typename _Distance>
251 void
252 __advance(_OutputIterator&, _Distance, output_iterator_tag) = delete;
253#endif
254
255 /// @endcond
256
257 /**
258 * @brief A generalization of pointer arithmetic.
259 * @param __i An input iterator.
260 * @param __n The @a delta by which to change @p __i.
261 *
262 * This increments `i` by `n`. For bidirectional and random access
263 * iterators, `__n` may be negative, in which case `__i` is decremented.
264 *
265 * For random access iterators, this uses their `+` and `-` operations
266 * and are constant time. For other %iterator classes they are linear time.
267 */
268 template<typename _InputIterator, typename _Distance>
269 __attribute__((__always_inline__))
270 inline _GLIBCXX17_CONSTEXPR void
271 advance(_InputIterator& __i, _Distance __n)
272 {
273#ifdef __glibcxx_concepts
274 // A type which satisfies the C++20 bidirectional_iterator concept might
275 // have input_iterator_tag as its iterator_category type, which would
276 // mean we select the __advance overload which cannot move backwards.
277 // For a C++20 random_access_iterator we might select the O(n) __advance
278 // if it doesn't meet the Cpp17RandomAccessIterator requirements.
279 // So for C++20 iterator types we can just choose to do the right thing.
280 if constexpr (__detail::__promotable_iterator<_InputIterator>
281 && ranges::__detail::__is_integer_like<_Distance>)
282 {
283 auto __d = static_cast<iter_difference_t<_InputIterator>>(__n);
284 if constexpr (random_access_iterator<_InputIterator>)
285 std::__advance(__i, __d, random_access_iterator_tag());
286 else if constexpr (bidirectional_iterator<_InputIterator>)
287 std::__advance(__i, __d, bidirectional_iterator_tag());
288 else
289 std::__advance(__i, __d, input_iterator_tag());
290 }
291 else // assume it meets the Cpp17InputIterator requirements:
292#endif
293 {
294 // concept requirements -- taken care of in __advance
295 typename iterator_traits<_InputIterator>::difference_type __d = __n;
296 std::__advance(__i, __d, std::__iterator_category(__i));
297 }
298 }
299
300#if __cplusplus >= 201103L
301
302 template<typename _InputIterator>
303 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
304 inline _GLIBCXX17_CONSTEXPR _InputIterator
305 next(_InputIterator __x, typename
306 iterator_traits<_InputIterator>::difference_type __n = 1)
307 {
308 // concept requirements
309 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
310 std::advance(__x, __n);
311 return __x;
312 }
313
314 template<typename _BidirectionalIterator>
315 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
316 inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
317 prev(_BidirectionalIterator __x, typename
318 iterator_traits<_BidirectionalIterator>::difference_type __n = 1)
319 {
320 // concept requirements
321 __glibcxx_function_requires(_BidirectionalIteratorConcept<
322 _BidirectionalIterator>)
323 std::advance(__x, -__n);
324 return __x;
325 }
326
327#endif // C++11
328
329 /// @cond undocumented
330#if __glibcxx_algorithm_iterator_requirements // C++ >= 20
331 template<typename _Iter>
332 consteval auto
333 __iter_concept_or_category()
334 {
335 if constexpr (__detail::__promotable_iterator<_Iter>)
336 {
337 using __type = __detail::__iter_traits<_Iter>::iterator_concept;
338 if constexpr (derived_from<__type, random_access_iterator_tag>)
339 return random_access_iterator_tag{};
340 else
341 return __type{};
342 }
343 else
344 return typename iterator_traits<_Iter>::iterator_category{};
345 }
346
347 template<typename _Iter>
348 __attribute__((__always_inline__))
349 constexpr auto
350 __iter_concept_or_category(const _Iter&)
351 { return std::__iter_concept_or_category<_Iter>(); }
352#else
353 template<typename _Iter>
354 __attribute__((__always_inline__))
355 inline _GLIBCXX_CONSTEXPR
356 typename iterator_traits<_Iter>::iterator_category
357 __iter_concept_or_category()
358 { return typename iterator_traits<_Iter>::iterator_category(); }
359
360 template<typename _Iter>
361 __attribute__((__always_inline__))
362 inline _GLIBCXX_CONSTEXPR
363 typename iterator_traits<_Iter>::iterator_category
364 __iter_concept_or_category(const _Iter&)
365 { return typename iterator_traits<_Iter>::iterator_category(); }
366#endif
367
368 // Like __is_random_access_iter, but based off of __iter_concept_or_category
369 // instead of iterator_traits::iterator_category.
370 template<typename _Iter,
371 typename _Cat = __decltype(__iter_concept_or_category<_Iter>())>
372 struct __is_any_random_access_iter
373#if __cplusplus >= 201103L
374 : is_base_of<random_access_iterator_tag, _Cat>
375#endif
376 { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; };
377
378// A wrapper around ranges::iter_move that also converts to the iterator's
379// value type.
380#if __cplusplus >= 202002L
381#define _GLIBCXX_ITER_MOVE(__it) \
382 std::iter_value_t<decltype(__it)>(std::ranges::iter_move(__it))
383#else
384#define _GLIBCXX_ITER_MOVE(__it) _GLIBCXX_MOVE(*__it)
385#endif
386
387 /* Mechanism for traversing ranges that are composed of "segments" of other
388 ranges, such as std::deque and ranges::join_view. The callback __func
389 is sequentially called on each constituent segment as a pair of inner
390 iterators. If the callback returns something other than the past-the-end
391 inner iterator, then the rest of the traversal gets short-circuited and
392 returns the iterator at which we stopped. */
393 template<typename _Iter, typename _Fn>
394#if __cplusplus >= 201103L
395 constexpr
396 __enable_if_t<__enable_for_each_segment<_Iter>, _Iter>
397#else
398 _Iter
399#endif
400 __for_each_segment(_Iter __first, _Iter __last, _Fn __func)
401 {
402 return _Iter::_S_for_each_segment(_GLIBCXX_MOVE(__first),
403 _GLIBCXX_MOVE(__last),
404 _GLIBCXX_MOVE(__func));
405 }
406
407 /// @endcond
408
409_GLIBCXX_END_NAMESPACE_VERSION
410} // namespace
411
412#endif /* _STL_ITERATOR_BASE_FUNCS_H */
concept_check.h
move.h
stl_iterator_base_types.h
assertions.h
std::move
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
std
ISO C++ entities toplevel namespace is std.
std::distance
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Definition stl_iterator_base_funcs.h:178
std::advance
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
Definition stl_iterator_base_funcs.h:271
std::__detail
Implementation details not part of the namespace std interface.
std::is_base_of
is_base_of
Definition type_traits:1666
std::iterator_traits
Traits class for iterators.
Definition stl_iterator_base_types.h:185
std::_List_iterator
A list::iterator.
Definition stl_list.h:575
std::_List_const_iterator
A list::const_iterator.
Definition stl_list.h:661
std::input_iterator_tag
Marking input iterators.
Definition stl_iterator_base_types.h:97
std::output_iterator_tag
Marking output iterators.
Definition stl_iterator_base_types.h:100
std::bidirectional_iterator_tag
Bidirectional iterators support a superset of forward iterator operations.
Definition stl_iterator_base_types.h:107
std::random_access_iterator_tag
Random-access iterators support a superset of bidirectional iterator operations.
Definition stl_iterator_base_types.h:111
std::derived_from
[concept.derived], concept derived_from
Definition concepts:76