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
70namespace std _GLIBCXX_VISIBILITY(default)
71{
72_GLIBCXX_BEGIN_NAMESPACE_VERSION
73
74_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
75 // Forward declaration for the overloads of __distance.
76 template <typename> struct _List_iterator;
77 template <typename> struct _List_const_iterator;
78_GLIBCXX_END_NAMESPACE_CONTAINER
79
80 template<typename _InputIterator>
81 inline _GLIBCXX14_CONSTEXPR
82 typename iterator_traits<_InputIterator>::difference_type
83 __distance(_InputIterator __first, _InputIterator __last,
84 input_iterator_tag)
85 {
86 // concept requirements
87 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
88
89 typename iterator_traits<_InputIterator>::difference_type __n = 0;
90 while (__first != __last)
91 {
92 ++__first;
93 ++__n;
94 }
95 return __n;
96 }
97
98 template<typename _RandomAccessIterator>
99 __attribute__((__always_inline__))
100 inline _GLIBCXX14_CONSTEXPR
101 typename iterator_traits<_RandomAccessIterator>::difference_type
102 __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
103 random_access_iterator_tag)
104 {
105 // concept requirements
106 __glibcxx_function_requires(_RandomAccessIteratorConcept<
107 _RandomAccessIterator>)
108 return __last - __first;
109 }
110
111#if _GLIBCXX_USE_CXX11_ABI
112 // Forward declaration because of the qualified call in distance.
113 template<typename _Tp>
114 ptrdiff_t
115 __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
116 _GLIBCXX_STD_C::_List_iterator<_Tp>,
117 input_iterator_tag);
118
119 template<typename _Tp>
120 ptrdiff_t
121 __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
122 _GLIBCXX_STD_C::_List_const_iterator<_Tp>,
123 input_iterator_tag);
124#endif
125
126#if __cplusplus >= 201103L
127 // Give better error if std::distance called with a non-Cpp17InputIterator.
128 template<typename _OutputIterator>
129 void
130 __distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete;
131#endif
132
133#ifdef __glibcxx_concepts
134/// @cond undocumented
135namespace __detail
136{
137
138 // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is
139 // at least as strong as ITER_TRAITS(Iter)::iterator_concept.
140 template<typename _Iter>
141 concept __iter_category_converts_to_concept
142 = convertible_to<typename __iter_traits<_Iter>::iterator_category,
143 typename __iter_traits<_Iter>::iterator_concept>;
144
145 // Satisfied if the type is a C++20 iterator that defines iterator_concept,
146 // and its iterator_concept is stronger than its iterator_category (if any).
147 // Used by std::distance and std::advance to detect iterators which should
148 // dispatch based on their C++20 concept not their C++17 category.
149 template<typename _Iter>
150 concept __promotable_iterator
151 = input_iterator<_Iter>
152 && requires { typename __iter_traits<_Iter>::iterator_concept; }
153 && ! __iter_category_converts_to_concept<_Iter>;
154
155} // namespace __detail
156/// @endcond
157#endif
158
159 /**
160 * @brief A generalization of pointer arithmetic.
161 * @param __first,__last Input iterators that form a valid range.
162 * @return The distance between them.
163 *
164 * Returns `n` such that `__first + n == __last`.
165 * This requires that `__last` must be reachable from `__first`, or
166 * for random access iterators either `__last` is reachable from `__first`
167 * or `__first` is reachable from `__last`. In the latter case, `n`
168 * may be negative.
169 *
170 * For random access iterators, this uses their `+` and `-` operations
171 * and is constant time. For other %iterator classes they are linear time.
172 */
173 template<typename _InputIterator>
174 _GLIBCXX_NODISCARD __attribute__((__always_inline__))
175 inline _GLIBCXX17_CONSTEXPR
176 typename iterator_traits<_InputIterator>::difference_type
177 distance(_InputIterator __first, _InputIterator __last)
178 {
179#ifdef __glibcxx_concepts
180 // A type which satisfies the C++20 random_access_iterator concept might
181 // have input_iterator_tag as its iterator_category type, which would
182 // mean we select the O(n) __distance. Or a C++20 std::input_iterator
183 // that is not a Cpp17InputIterator might have output_iterator_tag as
184 // its iterator_category type and then calling __distance with
185 // std::__iterator_category(__first) would be ill-formed.
186 // So for C++20 iterator types we can just choose to do the right thing.
187 if constexpr (__detail::__promotable_iterator<_InputIterator>)
188 {
189 if constexpr (random_access_iterator<_InputIterator>)
190 return __last - __first;
191 else
192 return std::__distance(std::move(__first), std::move(__last),
193 input_iterator_tag());
194 }
195 else // assume it meets the Cpp17InputIterator requirements:
196#endif
197 // concept requirements -- taken care of in __distance
198 return std::__distance(__first, __last,
199 std::__iterator_category(__first));
200 }
201
202 /// @cond undocumented
203
204 template<typename _InputIterator, typename _Distance>
205 inline _GLIBCXX14_CONSTEXPR void
206 __advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
207 {
208 // concept requirements
209 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
210 __glibcxx_assert(__n >= 0);
211 while (__n-- > 0)
212 ++__i;
213 }
214
215 template<typename _BidirectionalIterator, typename _Distance>
216 inline _GLIBCXX14_CONSTEXPR void
217 __advance(_BidirectionalIterator& __i, _Distance __n,
218 bidirectional_iterator_tag)
219 {
220 // concept requirements
221 __glibcxx_function_requires(_BidirectionalIteratorConcept<
222 _BidirectionalIterator>)
223 if (__n > 0)
224 while (__n--)
225 ++__i;
226 else
227 while (__n++)
228 --__i;
229 }
230
231 template<typename _RandomAccessIterator, typename _Distance>
232 inline _GLIBCXX14_CONSTEXPR void
233 __advance(_RandomAccessIterator& __i, _Distance __n,
234 random_access_iterator_tag)
235 {
236 // concept requirements
237 __glibcxx_function_requires(_RandomAccessIteratorConcept<
238 _RandomAccessIterator>)
239 if (__builtin_constant_p(__n) && __n == 1)
240 ++__i;
241 else if (__builtin_constant_p(__n) && __n == -1)
242 --__i;
243 else
244 __i += __n;
245 }
246
247#if __cplusplus >= 201103L
248 // Give better error if std::advance called with a non-Cpp17InputIterator.
249 template<typename _OutputIterator, typename _Distance>
250 void
251 __advance(_OutputIterator&, _Distance, output_iterator_tag) = delete;
252#endif
253
254 /// @endcond
255
256 /**
257 * @brief A generalization of pointer arithmetic.
258 * @param __i An input iterator.
259 * @param __n The @a delta by which to change @p __i.
260 *
261 * This increments `i` by `n`. For bidirectional and random access
262 * iterators, `__n` may be negative, in which case `__i` is decremented.
263 *
264 * For random access iterators, this uses their `+` and `-` operations
265 * and are constant time. For other %iterator classes they are linear time.
266 */
267 template<typename _InputIterator, typename _Distance>
268 __attribute__((__always_inline__))
269 inline _GLIBCXX17_CONSTEXPR void
270 advance(_InputIterator& __i, _Distance __n)
271 {
272#ifdef __glibcxx_concepts
273 // A type which satisfies the C++20 bidirectional_iterator concept might
274 // have input_iterator_tag as its iterator_category type, which would
275 // mean we select the __advance overload which cannot move backwards.
276 // For a C++20 random_access_iterator we might select the O(n) __advance
277 // if it doesn't meet the Cpp17RandomAccessIterator requirements.
278 // So for C++20 iterator types we can just choose to do the right thing.
279 if constexpr (__detail::__promotable_iterator<_InputIterator>
280 && ranges::__detail::__is_integer_like<_Distance>)
281 {
282 auto __d = static_cast<iter_difference_t<_InputIterator>>(__n);
283 if constexpr (random_access_iterator<_InputIterator>)
284 std::__advance(__i, __d, random_access_iterator_tag());
285 else if constexpr (bidirectional_iterator<_InputIterator>)
286 std::__advance(__i, __d, bidirectional_iterator_tag());
287 else
288 std::__advance(__i, __d, input_iterator_tag());
289 }
290 else // assume it meets the Cpp17InputIterator requirements:
291#endif
292 {
293 // concept requirements -- taken care of in __advance
294 typename iterator_traits<_InputIterator>::difference_type __d = __n;
295 std::__advance(__i, __d, std::__iterator_category(__i));
296 }
297 }
298
299#if __cplusplus >= 201103L
300
301 template<typename _InputIterator>
302 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
303 inline _GLIBCXX17_CONSTEXPR _InputIterator
304 next(_InputIterator __x, typename
305 iterator_traits<_InputIterator>::difference_type __n = 1)
306 {
307 // concept requirements
308 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
309 std::advance(__x, __n);
310 return __x;
311 }
312
313 template<typename _BidirectionalIterator>
314 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
315 inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
316 prev(_BidirectionalIterator __x, typename
317 iterator_traits<_BidirectionalIterator>::difference_type __n = 1)
318 {
319 // concept requirements
320 __glibcxx_function_requires(_BidirectionalIteratorConcept<
321 _BidirectionalIterator>)
322 std::advance(__x, -__n);
323 return __x;
324 }
325
326#endif // C++11
327
328 /// @cond undocumented
329#if __glibcxx_algorithm_iterator_requirements // C++ >= 20
330 template<typename _Iter>
331 consteval auto
332 __iter_concept_or_category()
333 {
334 if constexpr (__detail::__promotable_iterator<_Iter>)
335 {
336 using __type = __detail::__iter_traits<_Iter>::iterator_concept;
337 if constexpr (derived_from<__type, random_access_iterator_tag>)
338 return random_access_iterator_tag{};
339 else
340 return __type{};
341 }
342 else
343 return typename iterator_traits<_Iter>::iterator_category{};
344 }
345
346 template<typename _Iter>
347 __attribute__((__always_inline__))
348 constexpr auto
349 __iter_concept_or_category(const _Iter&)
350 { return std::__iter_concept_or_category<_Iter>(); }
351#else
352 template<typename _Iter>
353 __attribute__((__always_inline__))
354 inline _GLIBCXX_CONSTEXPR
355 typename iterator_traits<_Iter>::iterator_category
356 __iter_concept_or_category()
357 { return typename iterator_traits<_Iter>::iterator_category(); }
358
359 template<typename _Iter>
360 __attribute__((__always_inline__))
361 inline _GLIBCXX_CONSTEXPR
362 typename iterator_traits<_Iter>::iterator_category
363 __iter_concept_or_category(const _Iter&)
364 { return typename iterator_traits<_Iter>::iterator_category(); }
365#endif
366
367 // Like __is_random_access_iter, but based off of __iter_concept_or_category
368 // instead of iterator_traits::iterator_category.
369 template<typename _Iter,
370 typename _Cat = __decltype(__iter_concept_or_category<_Iter>())>
371 struct __is_any_random_access_iter
372#if __cplusplus >= 201103L
373 : is_base_of<random_access_iterator_tag, _Cat>
374#endif
375 { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; };
376
377// A wrapper around ranges::iter_move that also converts to the iterator's
378// value type.
379#if __cplusplus >= 202002L
380#define _GLIBCXX_ITER_MOVE(__it) \
381 std::iter_value_t<decltype(__it)>(std::ranges::iter_move(__it))
382#else
383#define _GLIBCXX_ITER_MOVE(__it) _GLIBCXX_MOVE(*__it)
384#endif
385
386 /// @endcond
387
388_GLIBCXX_END_NAMESPACE_VERSION
389} // namespace
390
391#endif /* _STL_ITERATOR_BASE_FUNCS_H */
concept_check.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:177
std::advance
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
Definition stl_iterator_base_funcs.h:270
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:183
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:95
std::output_iterator_tag
Marking output iterators.
Definition stl_iterator_base_types.h:98
std::bidirectional_iterator_tag
Bidirectional iterators support a superset of forward iterator operations.
Definition stl_iterator_base_types.h:105
std::random_access_iterator_tag
Random-access iterators support a superset of bidirectional iterator operations.
Definition stl_iterator_base_types.h:109
std::derived_from
[concept.derived], concept derived_from
Definition concepts:76