libstdc++
stl_iterator_base_funcs.h
Go to the documentation of this file.
1// Functions used by iterators -*- C++ -*-
2
3// Copyright (C) 2001-2025 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>
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
83 __distance(_InputIterator __first, _InputIterator __last,
85 {
86 // concept requirements
87 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
88
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
102 __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
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>,
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>,
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
134namespace __detail
135{
136 // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is
137 // at least as strong as ITER_TRAITS(Iter)::iterator_concept.
138 template<typename _Iter>
139 concept __iter_category_converts_to_concept
140 = convertible_to<typename __iter_traits<_Iter>::iterator_category,
141 typename __iter_traits<_Iter>::iterator_concept>;
142
143 // Satisfied if the type is a C++20 iterator that defines iterator_concept,
144 // and its iterator_concept is stronger than its iterator_category (if any).
145 // Used by std::distance and std::advance to detect iterators which should
146 // dispatch based on their C++20 concept not their C++17 category.
147 template<typename _Iter>
148 concept __promotable_iterator
149 = input_iterator<_Iter>
150 && requires { typename __iter_traits<_Iter>::iterator_concept; }
151 && ! __iter_category_converts_to_concept<_Iter>;
152} // namespace __detail
153#endif
154
155 /**
156 * @brief A generalization of pointer arithmetic.
157 * @param __first An input iterator.
158 * @param __last An input iterator.
159 * @return The distance between them.
160 *
161 * Returns @c n such that __first + n == __last. This requires
162 * that @p __last must be reachable from @p __first. Note that @c
163 * n may be negative.
164 *
165 * For random access iterators, this uses their @c + and @c - operations
166 * and are constant time. For other %iterator classes they are linear time.
167 */
168 template<typename _InputIterator>
169 _GLIBCXX_NODISCARD __attribute__((__always_inline__))
170 inline _GLIBCXX17_CONSTEXPR
172 distance(_InputIterator __first, _InputIterator __last)
173 {
174#ifdef __glibcxx_concepts
175 // A type which satisfies the C++20 random_access_iterator concept might
176 // have input_iterator_tag as its iterator_category type, which would
177 // mean we select the O(n) __distance. Or a C++20 std::input_iterator
178 // that is not a Cpp17InputIterator might have output_iterator_tag as
179 // its iterator_category type and then calling __distance with
180 // std::__iterator_category(__first) would be ill-formed.
181 // So for C++20 iterator types we can just choose to do the right thing.
182 if constexpr (__detail::__promotable_iterator<_InputIterator>)
183 {
184 if constexpr (random_access_iterator<_InputIterator>)
185 return __last - __first;
186 else
187 return std::__distance(std::move(__first), std::move(__last),
189 }
190 else // assume it meets the Cpp17InputIterator requirements:
191#endif
192 // concept requirements -- taken care of in __distance
193 return std::__distance(__first, __last,
194 std::__iterator_category(__first));
195 }
196
197 template<typename _InputIterator, typename _Distance>
198 inline _GLIBCXX14_CONSTEXPR void
199 __advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
200 {
201 // concept requirements
202 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
203 __glibcxx_assert(__n >= 0);
204 while (__n--)
205 ++__i;
206 }
207
208 template<typename _BidirectionalIterator, typename _Distance>
209 inline _GLIBCXX14_CONSTEXPR void
210 __advance(_BidirectionalIterator& __i, _Distance __n,
212 {
213 // concept requirements
214 __glibcxx_function_requires(_BidirectionalIteratorConcept<
215 _BidirectionalIterator>)
216 if (__n > 0)
217 while (__n--)
218 ++__i;
219 else
220 while (__n++)
221 --__i;
222 }
223
224 template<typename _RandomAccessIterator, typename _Distance>
225 inline _GLIBCXX14_CONSTEXPR void
226 __advance(_RandomAccessIterator& __i, _Distance __n,
228 {
229 // concept requirements
230 __glibcxx_function_requires(_RandomAccessIteratorConcept<
231 _RandomAccessIterator>)
232 if (__builtin_constant_p(__n) && __n == 1)
233 ++__i;
234 else if (__builtin_constant_p(__n) && __n == -1)
235 --__i;
236 else
237 __i += __n;
238 }
239
240#if __cplusplus >= 201103L
241 // Give better error if std::advance called with a non-Cpp17InputIterator.
242 template<typename _OutputIterator, typename _Distance>
243 void
244 __advance(_OutputIterator&, _Distance, output_iterator_tag) = delete;
245#endif
246
247 /**
248 * @brief A generalization of pointer arithmetic.
249 * @param __i An input iterator.
250 * @param __n The @a delta by which to change @p __i.
251 * @return Nothing.
252 *
253 * This increments @p i by @p n. For bidirectional and random access
254 * iterators, @p __n may be negative, in which case @p __i is decremented.
255 *
256 * For random access iterators, this uses their @c + and @c - operations
257 * and are constant time. For other %iterator classes they are linear time.
258 */
259 template<typename _InputIterator, typename _Distance>
260 __attribute__((__always_inline__))
261 inline _GLIBCXX17_CONSTEXPR void
262 advance(_InputIterator& __i, _Distance __n)
263 {
264#ifdef __glibcxx_concepts
265 // A type which satisfies the C++20 bidirectional_iterator concept might
266 // have input_iterator_tag as its iterator_category type, which would
267 // mean we select the __advance overload which cannot move backwards.
268 // A C++20 random_access_iterator we might select the O(n) __advance
269 // if it doesn't meet the Cpp17RandomAccessIterator requirements.
270 // So for C++20 iterator types we can just choose to do the right thing.
271 if constexpr (__detail::__promotable_iterator<_InputIterator>
272 && ranges::__detail::__is_integer_like<_Distance>)
273 {
274 auto __d = static_cast<iter_difference_t<_InputIterator>>(__n);
275 if constexpr (random_access_iterator<_InputIterator>)
276 std::__advance(__i, __d, random_access_iterator_tag());
277 else if constexpr (bidirectional_iterator<_InputIterator>)
278 std::__advance(__i, __d, bidirectional_iterator_tag());
279 else
280 std::__advance(__i, __d, input_iterator_tag());
281 }
282 else // assume it meets the Cpp17InputIterator requirements:
283#endif
284 {
285 // concept requirements -- taken care of in __advance
287 std::__advance(__i, __d, std::__iterator_category(__i));
288 }
289 }
290
291#if __cplusplus >= 201103L
292
293 template<typename _InputIterator>
294 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
295 inline _GLIBCXX17_CONSTEXPR _InputIterator
296 next(_InputIterator __x, typename
297 iterator_traits<_InputIterator>::difference_type __n = 1)
298 {
299 // concept requirements
300 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
301 std::advance(__x, __n);
302 return __x;
303 }
304
305 template<typename _BidirectionalIterator>
306 _GLIBCXX_NODISCARD [[__gnu__::__always_inline__]]
307 inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
308 prev(_BidirectionalIterator __x, typename
310 {
311 // concept requirements
312 __glibcxx_function_requires(_BidirectionalIteratorConcept<
313 _BidirectionalIterator>)
314 std::advance(__x, -__n);
315 return __x;
316 }
317
318#endif // C++11
319
320_GLIBCXX_END_NAMESPACE_VERSION
321} // namespace
322
323#endif /* _STL_ITERATOR_BASE_FUNCS_H */
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr iterator_traits< _Iter >::iterator_category __iterator_category(const _Iter &)
ISO C++ entities toplevel namespace is std.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
Implementation details not part of the namespace std interface.
A list::iterator.
Definition stl_list.h:575
A list::const_iterator.
Definition stl_list.h:661
Marking input iterators.
Marking output iterators.
Bidirectional iterators support a superset of forward iterator operations.
Random-access iterators support a superset of bidirectional iterator operations.
Traits class for iterators.