Skip to content

Commit c5d94b8

Browse files
committed
Optimize 0-sized array iterators
1 parent 03f1150 commit c5d94b8

File tree

1 file changed

+67
-34
lines changed

1 file changed

+67
-34
lines changed

libcxx/include/__iterator/static_bounded_iter.h

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,37 @@ _LIBCPP_PUSH_MACROS
3131

3232
_LIBCPP_BEGIN_NAMESPACE_STD
3333

34+
template <class _Iterator, size_t _Size>
35+
struct __static_bounded_iter_storage {
36+
_LIBCPP_HIDE_FROM_ABI
37+
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter_storage(_Iterator __current, _Iterator __begin)
38+
: __current_(__current), __begin_(__begin) {}
39+
40+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __current_; }
41+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __current_; }
42+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __begin_; }
43+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __begin_ + _Size; }
44+
45+
private:
46+
_Iterator __current_; // current iterator
47+
_Iterator __begin_; // start of the valid range, which is [__begin_, __begin_ + _Size)
48+
};
49+
50+
template <class _Iterator, size_t _Size>
51+
struct __static_bounded_iter_storage<_Iterator, 0> {
52+
_LIBCPP_HIDE_FROM_ABI
53+
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter_storage(_Iterator __current, _Iterator /* __begin */)
54+
: __current_(__current) {}
55+
56+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __current_; }
57+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __current_; }
58+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __current_; }
59+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __current_ + _Size; }
60+
61+
private:
62+
_Iterator __current_; // current iterator
63+
};
64+
3465
// This is an iterator wrapper for contiguous iterators that points within a range
3566
// whose size is known at compile-time. This is very similar to `__bounded_iter`,
3667
// except that we don't have to store the end of the range in physical memory since
@@ -60,8 +91,7 @@ struct __static_bounded_iter {
6091
template <class _OtherIterator, __enable_if_t<is_convertible<_OtherIterator, _Iterator>::value, int> = 0>
6192
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
6293
__static_bounded_iter(__static_bounded_iter<_OtherIterator, _Size> const& __other) _NOEXCEPT
63-
: __current_(__other.__current_),
64-
__begin_(__other.__begin_) {}
94+
: __storage_(__other.__storage_.__current(), __other.__storage_.__begin()) {}
6595

6696
// Assign a bounded iterator to another one, rebinding the bounds of the iterator as well.
6797
_LIBCPP_HIDE_FROM_ABI __static_bounded_iter& operator=(__static_bounded_iter const&) = default;
@@ -72,7 +102,7 @@ struct __static_bounded_iter {
72102
// by the provided [begin, begin + _Size] range.
73103
_LIBCPP_HIDE_FROM_ABI
74104
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter(_Iterator __current, _Iterator __begin)
75-
: __current_(__current), __begin_(__begin) {
105+
: __storage_(__current, __begin) {
76106
_LIBCPP_ASSERT_INTERNAL(
77107
__begin <= __current, "__static_bounded_iter(current, begin): current and begin are inconsistent");
78108
_LIBCPP_ASSERT_INTERNAL(
@@ -86,32 +116,33 @@ struct __static_bounded_iter {
86116
// Dereference and indexing operations.
87117
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT {
88118
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
89-
__current_ != __end(), "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
90-
return *__current_;
119+
__current() != __end(), "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
120+
return *__current();
91121
}
92122

93123
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT {
94124
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
95-
__current_ != __end(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
96-
return std::__to_address(__current_);
125+
__current() != __end(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
126+
return std::__to_address(__current());
97127
}
98128

99129
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT {
100130
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
101-
__n >= __begin_ - __current_, "__static_bounded_iter::operator[]: Attempt to index an iterator past the start");
131+
__n >= __begin() - __current(),
132+
"__static_bounded_iter::operator[]: Attempt to index an iterator past the start");
102133
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
103-
__n < __end() - __current_,
134+
__n < __end() - __current(),
104135
"__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end");
105-
return __current_[__n];
136+
return __current()[__n];
106137
}
107138

108139
// Arithmetic operations.
109140
//
110141
// These operations check that the iterator remains within `[begin, end]`.
111142
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator++() _NOEXCEPT {
112143
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
113-
__current_ != __end(), "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
114-
++__current_;
144+
__current() != __end(), "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
145+
++__current();
115146
return *this;
116147
}
117148
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter operator++(int) _NOEXCEPT {
@@ -122,8 +153,8 @@ struct __static_bounded_iter {
122153

123154
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator--() _NOEXCEPT {
124155
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
125-
__current_ != __begin_, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
126-
--__current_;
156+
__current() != __begin(), "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
157+
--__current();
127158
return *this;
128159
}
129160
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter operator--(int) _NOEXCEPT {
@@ -134,11 +165,11 @@ struct __static_bounded_iter {
134165

135166
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator+=(difference_type __n) _NOEXCEPT {
136167
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
137-
__n >= __begin_ - __current_,
168+
__n >= __begin() - __current(),
138169
"__static_bounded_iter::operator+=: Attempt to rewind an iterator past the start");
139170
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
140-
__n <= __end() - __current_, "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end");
141-
__current_ += __n;
171+
__n <= __end() - __current(), "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end");
172+
__current() += __n;
142173
return *this;
143174
}
144175
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __static_bounded_iter
@@ -156,11 +187,11 @@ struct __static_bounded_iter {
156187

157188
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator-=(difference_type __n) _NOEXCEPT {
158189
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
159-
__n <= __current_ - __begin_,
190+
__n <= __current() - __begin(),
160191
"__static_bounded_iter::operator-=: Attempt to rewind an iterator past the start");
161192
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
162-
__n >= __current_ - __end(), "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end");
163-
__current_ -= __n;
193+
__n >= __current() - __end(), "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end");
194+
__current() -= __n;
164195
return *this;
165196
}
166197
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __static_bounded_iter
@@ -171,7 +202,7 @@ struct __static_bounded_iter {
171202
}
172203
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend difference_type
173204
operator-(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
174-
return __x.__current_ - __y.__current_;
205+
return __x.__current() - __y.__current();
175206
}
176207

177208
// Comparison operations.
@@ -182,42 +213,42 @@ struct __static_bounded_iter {
182213
// if they have different validity ranges.
183214
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
184215
operator==(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
185-
return __x.__current_ == __y.__current_;
216+
return __x.__current() == __y.__current();
186217
}
187218

188219
#if _LIBCPP_STD_VER <= 17
189220
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
190221
operator!=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
191-
return __x.__current_ != __y.__current_;
222+
return __x.__current() != __y.__current();
192223
}
193224

194225
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
195226
operator<(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
196-
return __x.__current_ < __y.__current_;
227+
return __x.__current() < __y.__current();
197228
}
198229
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
199230
operator>(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
200-
return __x.__current_ > __y.__current_;
231+
return __x.__current() > __y.__current();
201232
}
202233
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
203234
operator<=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
204-
return __x.__current_ <= __y.__current_;
235+
return __x.__current() <= __y.__current();
205236
}
206237
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
207238
operator>=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
208-
return __x.__current_ >= __y.__current_;
239+
return __x.__current() >= __y.__current();
209240
}
210241

211242
#else
212243
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
213244
operator<=>(__static_bounded_iter const& __x, __static_bounded_iter const& __y) noexcept {
214245
if constexpr (three_way_comparable<_Iterator, strong_ordering>) {
215-
return __x.__current_ <=> __y.__current_;
246+
return __x.__current() <=> __y.__current();
216247
} else {
217-
if (__x.__current_ < __y.__current_)
248+
if (__x.__current() < __y.__current())
218249
return strong_ordering::less;
219250

220-
if (__x.__current_ == __y.__current_)
251+
if (__x.__current() == __y.__current())
221252
return strong_ordering::equal;
222253

223254
return strong_ordering::greater;
@@ -230,10 +261,12 @@ struct __static_bounded_iter {
230261
friend struct pointer_traits;
231262
template <class, size_t, class>
232263
friend struct __static_bounded_iter;
233-
_Iterator __current_; // current iterator
234-
_Iterator __begin_; // start of the valid range, which is [__begin_, __begin_ + _Size)
264+
__static_bounded_iter_storage<_Iterator, _Size> __storage_;
235265

236-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __begin_ + _Size; }
266+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __storage_.__current(); }
267+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __storage_.__current(); }
268+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __storage_.__begin(); }
269+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __storage_.__end(); }
237270
};
238271

239272
template <size_t _Size, class _It>
@@ -254,7 +287,7 @@ struct pointer_traits<__static_bounded_iter<_Iterator, _Size> > {
254287
using difference_type = typename pointer_traits<_Iterator>::difference_type;
255288

256289
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static element_type* to_address(pointer __it) _NOEXCEPT {
257-
return std::__to_address(__it.__current_);
290+
return std::__to_address(__it.__current());
258291
}
259292
};
260293

0 commit comments

Comments
 (0)