Skip to content

Commit

Permalink
Optimize 0-sized array iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
ldionne committed Oct 21, 2024
1 parent 03f1150 commit c5d94b8
Showing 1 changed file with 67 additions and 34 deletions.
101 changes: 67 additions & 34 deletions libcxx/include/__iterator/static_bounded_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ _LIBCPP_PUSH_MACROS

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Iterator, size_t _Size>
struct __static_bounded_iter_storage {
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter_storage(_Iterator __current, _Iterator __begin)
: __current_(__current), __begin_(__begin) {}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __current_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __current_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __begin_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __begin_ + _Size; }

private:
_Iterator __current_; // current iterator
_Iterator __begin_; // start of the valid range, which is [__begin_, __begin_ + _Size)
};

template <class _Iterator, size_t _Size>
struct __static_bounded_iter_storage<_Iterator, 0> {
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter_storage(_Iterator __current, _Iterator /* __begin */)
: __current_(__current) {}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __current_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __current_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __current_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __current_ + _Size; }

private:
_Iterator __current_; // current iterator
};

// This is an iterator wrapper for contiguous iterators that points within a range
// whose size is known at compile-time. This is very similar to `__bounded_iter`,
// except that we don't have to store the end of the range in physical memory since
Expand Down Expand Up @@ -60,8 +91,7 @@ struct __static_bounded_iter {
template <class _OtherIterator, __enable_if_t<is_convertible<_OtherIterator, _Iterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
__static_bounded_iter(__static_bounded_iter<_OtherIterator, _Size> const& __other) _NOEXCEPT
: __current_(__other.__current_),
__begin_(__other.__begin_) {}
: __storage_(__other.__storage_.__current(), __other.__storage_.__begin()) {}

// Assign a bounded iterator to another one, rebinding the bounds of the iterator as well.
_LIBCPP_HIDE_FROM_ABI __static_bounded_iter& operator=(__static_bounded_iter const&) = default;
Expand All @@ -72,7 +102,7 @@ struct __static_bounded_iter {
// by the provided [begin, begin + _Size] range.
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __static_bounded_iter(_Iterator __current, _Iterator __begin)
: __current_(__current), __begin_(__begin) {
: __storage_(__current, __begin) {
_LIBCPP_ASSERT_INTERNAL(
__begin <= __current, "__static_bounded_iter(current, begin): current and begin are inconsistent");
_LIBCPP_ASSERT_INTERNAL(
Expand All @@ -86,32 +116,33 @@ struct __static_bounded_iter {
// Dereference and indexing operations.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__current_ != __end(), "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
return *__current_;
__current() != __end(), "__static_bounded_iter::operator*: Attempt to dereference an iterator at the end");
return *__current();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__current_ != __end(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
return std::__to_address(__current_);
__current() != __end(), "__static_bounded_iter::operator->: Attempt to dereference an iterator at the end");
return std::__to_address(__current());
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n >= __begin_ - __current_, "__static_bounded_iter::operator[]: Attempt to index an iterator past the start");
__n >= __begin() - __current(),
"__static_bounded_iter::operator[]: Attempt to index an iterator past the start");
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n < __end() - __current_,
__n < __end() - __current(),
"__static_bounded_iter::operator[]: Attempt to index an iterator at or past the end");
return __current_[__n];
return __current()[__n];
}

// Arithmetic operations.
//
// These operations check that the iterator remains within `[begin, end]`.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator++() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__current_ != __end(), "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
++__current_;
__current() != __end(), "__static_bounded_iter::operator++: Attempt to advance an iterator past the end");
++__current();
return *this;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter operator++(int) _NOEXCEPT {
Expand All @@ -122,8 +153,8 @@ struct __static_bounded_iter {

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator--() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__current_ != __begin_, "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
--__current_;
__current() != __begin(), "__static_bounded_iter::operator--: Attempt to rewind an iterator past the start");
--__current();
return *this;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter operator--(int) _NOEXCEPT {
Expand All @@ -134,11 +165,11 @@ struct __static_bounded_iter {

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator+=(difference_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n >= __begin_ - __current_,
__n >= __begin() - __current(),
"__static_bounded_iter::operator+=: Attempt to rewind an iterator past the start");
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n <= __end() - __current_, "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end");
__current_ += __n;
__n <= __end() - __current(), "__static_bounded_iter::operator+=: Attempt to advance an iterator past the end");
__current() += __n;
return *this;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __static_bounded_iter
Expand All @@ -156,11 +187,11 @@ struct __static_bounded_iter {

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __static_bounded_iter& operator-=(difference_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n <= __current_ - __begin_,
__n <= __current() - __begin(),
"__static_bounded_iter::operator-=: Attempt to rewind an iterator past the start");
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__n >= __current_ - __end(), "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end");
__current_ -= __n;
__n >= __current() - __end(), "__static_bounded_iter::operator-=: Attempt to advance an iterator past the end");
__current() -= __n;
return *this;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend __static_bounded_iter
Expand All @@ -171,7 +202,7 @@ struct __static_bounded_iter {
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 friend difference_type
operator-(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ - __y.__current_;
return __x.__current() - __y.__current();
}

// Comparison operations.
Expand All @@ -182,42 +213,42 @@ struct __static_bounded_iter {
// if they have different validity ranges.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator==(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ == __y.__current_;
return __x.__current() == __y.__current();
}

#if _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator!=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ != __y.__current_;
return __x.__current() != __y.__current();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator<(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ < __y.__current_;
return __x.__current() < __y.__current();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator>(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ > __y.__current_;
return __x.__current() > __y.__current();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator<=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ <= __y.__current_;
return __x.__current() <= __y.__current();
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
operator>=(__static_bounded_iter const& __x, __static_bounded_iter const& __y) _NOEXCEPT {
return __x.__current_ >= __y.__current_;
return __x.__current() >= __y.__current();
}

#else
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
operator<=>(__static_bounded_iter const& __x, __static_bounded_iter const& __y) noexcept {
if constexpr (three_way_comparable<_Iterator, strong_ordering>) {
return __x.__current_ <=> __y.__current_;
return __x.__current() <=> __y.__current();
} else {
if (__x.__current_ < __y.__current_)
if (__x.__current() < __y.__current())
return strong_ordering::less;

if (__x.__current_ == __y.__current_)
if (__x.__current() == __y.__current())
return strong_ordering::equal;

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

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __begin_ + _Size; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator& __current() _NOEXCEPT { return __storage_.__current(); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __current() const _NOEXCEPT { return __storage_.__current(); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __begin() const _NOEXCEPT { return __storage_.__begin(); }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iterator __end() const _NOEXCEPT { return __storage_.__end(); }
};

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

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static element_type* to_address(pointer __it) _NOEXCEPT {
return std::__to_address(__it.__current_);
return std::__to_address(__it.__current());
}
};

Expand Down

0 comments on commit c5d94b8

Please sign in to comment.