3434
3535namespace gsl
3636{
37+
38+ template <typename T, typename Allocator>
39+ class dyn_array ;
40+
3741namespace details
3842{
3943 template <typename T, typename Allocator = std::allocator<T>>
@@ -164,19 +168,16 @@ namespace details
164168 template <typename T>
165169 class dyn_array_iterator
166170 {
167- using size_type = std::size_t ;
168-
169171 public:
170172 using difference_type = std::ptrdiff_t ;
171- using value_type = T ;
173+ using value_type = std:: remove_cv_t <T> ;
172174 using pointer = T*;
173175 using reference = T&;
174176 using const_reference = const T&;
175177 using iterator_category = std::random_access_iterator_tag;
176178
177- #if defined(__cpp_lib_ranges) && (__cpp_lib_ranges >= 201911L)
178- constexpr dyn_array_iterator () = default;
179- #endif /* __cpp_lib_ranges >= 201911L */
179+ private:
180+ using size_type = std::size_t ;
180181
181182 constexpr dyn_array_iterator (pointer ptr, size_type pos, size_type end_pos)
182183 : _ptr{ptr}, _pos{pos}, _end_pos{end_pos}
@@ -185,22 +186,86 @@ namespace details
185186 Ensures (_pos <= _end_pos);
186187 }
187188
189+ public:
190+ #if defined(__cpp_lib_ranges) && (__cpp_lib_ranges >= 201911L)
191+ constexpr dyn_array_iterator () = default;
192+ #endif /* __cpp_lib_ranges >= 201911L */
193+
194+ template <typename Allocator>
195+ constexpr dyn_array_iterator (dyn_array<std::remove_const_t <T>, Allocator>& arr)
196+ : dyn_array_iterator{arr.data (), 0 , arr.size ()}
197+ {}
198+
199+ template <typename Allocator, typename U = T,
200+ std::enable_if_t <std::is_const<U>::value, bool > = true >
201+ constexpr dyn_array_iterator (const dyn_array<std::remove_const_t <T>, Allocator>& arr)
202+ : dyn_array_iterator{arr.data (), 0 , arr.size ()}
203+ {}
204+
205+ template <typename U,
206+ std::enable_if_t <std::is_const<T>::value && !std::is_const<U>::value &&
207+ std::is_same<std::remove_const_t <T>, U>::value,
208+ bool > = true >
209+ constexpr dyn_array_iterator (const dyn_array_iterator<U>& other)
210+ : dyn_array_iterator{other._ptr , other._pos , other._end_pos }
211+ {}
212+
188213#if defined(_MSC_VER) && defined(__cpp_lib_ranges) && (__cpp_lib_ranges >= 201911L)
189214 constexpr operator pointer () const { return _ptr + gsl::narrow<size_type>(_pos); }
190215#endif /* defined(_MSC_VER) && __cpp_lib_ranges >= 201911L */
191216
192- constexpr auto operator ==(const dyn_array_iterator& other) const
217+ template <typename U,
218+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
219+ true >
220+ constexpr auto operator ==(const dyn_array_iterator<U>& other) const
193221 {
194222 Expects (_ptr == other._ptr );
195223 Expects (_end_pos == other._end_pos );
196224 return _pos == other._pos ;
197225 }
198226
199- constexpr auto operator !=(const dyn_array_iterator& other) const
227+ template <typename U,
228+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
229+ true >
230+ constexpr auto operator !=(const dyn_array_iterator<U>& other) const
200231 {
201232 return !(*this == other);
202233 }
203234
235+ template <typename U,
236+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
237+ true >
238+ constexpr auto operator <(const dyn_array_iterator<U>& other) const
239+ {
240+ Expects (_ptr == other._ptr );
241+ Expects (_end_pos == other._end_pos );
242+ return _pos < other._pos ;
243+ }
244+
245+ template <typename U,
246+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
247+ true >
248+ constexpr auto operator >(const dyn_array_iterator<U>& other) const
249+ {
250+ return other < *this ;
251+ }
252+
253+ template <typename U,
254+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
255+ true >
256+ constexpr auto operator <=(const dyn_array_iterator<U>& other) const
257+ {
258+ return !(other < *this );
259+ }
260+
261+ template <typename U,
262+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
263+ true >
264+ constexpr auto operator >=(const dyn_array_iterator<U>& other) const
265+ {
266+ return !(*this < other);
267+ }
268+
204269 constexpr auto operator *() const -> reference
205270 {
206271 Expects (_ptr != nullptr );
@@ -258,30 +323,32 @@ namespace details
258323 return dyn_array_iterator{_ptr, gsl::narrow<size_type>(new_pos), _end_pos};
259324 }
260325
326+ friend constexpr auto operator +(difference_type diff, const dyn_array_iterator& other)
327+ {
328+ return other + diff;
329+ }
330+
261331 constexpr auto operator -(difference_type diff) const { return *this + (-diff); }
262332
263- constexpr auto operator -(const dyn_array_iterator& other) const
333+ template <typename U,
334+ std::enable_if_t <std::is_same<std::remove_cv_t <U>, value_type>::value, bool > =
335+ true >
336+ constexpr auto operator -(const dyn_array_iterator<U>& other) const
264337 {
265338 Expects (_ptr == other._ptr );
266339 Expects (_end_pos == other._end_pos );
267340 return gsl::narrow<difference_type>(_pos) - gsl::narrow<difference_type>(other._pos );
268341 }
269342
270- constexpr auto operator [](size_type pos) -> reference
271- {
272- Expects (_pos + pos < _end_pos);
273- return _ptr[_pos + pos];
274- }
275-
276- constexpr auto operator [](size_type pos) const -> const_reference
277- {
278- return const_cast <dyn_array_iterator&>(*this ).operator [](pos);
279- }
343+ constexpr auto operator [](difference_type diff) const -> reference { return *(*this + diff); }
280344
281345 private:
282346 pointer _ptr{};
283347 size_type _pos{};
284348 size_type _end_pos{};
349+
350+ template <typename >
351+ friend class dyn_array_iterator ;
285352 };
286353} // namespace details
287354
@@ -385,8 +452,8 @@ public:
385452 constexpr auto data () { return base::data (); }
386453 constexpr auto data () const -> const T* { return const_cast <dyn_array&>(*this ).data (); }
387454
388- constexpr auto begin () { return iterator{data (), 0 , size () }; }
389- constexpr auto begin () const { return const_iterator{data (), 0 , size () }; }
455+ constexpr auto begin () { return iterator{* this }; }
456+ constexpr auto begin () const { return const_iterator{* this }; }
390457 constexpr auto cbegin () const { return begin (); }
391458
392459 constexpr auto rbegin () { return reverse_iterator{end ()}; }
@@ -401,8 +468,8 @@ public:
401468 }
402469#endif /* _MSC_VER */
403470
404- constexpr auto end () { return iterator{ data (), size (), size ()} ; }
405- constexpr auto end () const { return const_iterator{ data (), size (), size ()} ; }
471+ constexpr auto end () { return begin () + size (); }
472+ constexpr auto end () const { return begin () + size (); }
406473 constexpr auto cend () const { return end (); }
407474
408475 constexpr auto rend () { return reverse_iterator{begin ()}; }
0 commit comments