| 2813 | */ |
| 2814 | template <typename value_type_> |
| 2815 | class strided_ptr { |
| 2816 | std::byte *data_; |
| 2817 | std::size_t stride_; |
| 2818 | |
| 2819 | public: |
| 2820 | using value_type = value_type_; |
| 2821 | using pointer = value_type_ *; |
| 2822 | using reference = value_type_ &; |
| 2823 | using difference_type = std::ptrdiff_t; |
| 2824 | using iterator_category = std::random_access_iterator_tag; |
| 2825 | |
| 2826 | strided_ptr(std::byte *data, std::size_t stride_bytes) : data_(data), stride_(stride_bytes) { |
| 2827 | assert(data_ && "Pointer must not be null, as NULL arithmetic is undefined"); |
| 2828 | } |
| 2829 | #if defined(__cpp_lib_assume_aligned) // Not available in Apple Clang |
| 2830 | reference operator*() const noexcept { |
| 2831 | return *std::launder(std::assume_aligned<1>(reinterpret_cast<pointer>(data_))); |
| 2832 | } |
| 2833 | reference operator[](difference_type i) const noexcept { |
| 2834 | return *std::launder(std::assume_aligned<1>(reinterpret_cast<pointer>(data_ + i * stride_))); |
| 2835 | } |
| 2836 | #else |
| 2837 | reference operator*() const noexcept { return *reinterpret_cast<pointer>(data_); } |
| 2838 | reference operator[](difference_type i) const noexcept { return *reinterpret_cast<pointer>(data_ + i * stride_); } |
| 2839 | #endif // defined(__cpp_lib_assume_aligned) |
| 2840 | |
| 2841 | // clang-format off |
| 2842 | pointer operator->() const noexcept { return &operator*(); } |
| 2843 | strided_ptr &operator++() noexcept { data_ += stride_; return *this; } |
| 2844 | strided_ptr operator++(int) noexcept { strided_ptr temp = *this; ++(*this); return temp; } |
| 2845 | strided_ptr &operator--() noexcept { data_ -= stride_; return *this; } |
| 2846 | strided_ptr operator--(int) noexcept { strided_ptr temp = *this; --(*this); return temp; } |
| 2847 | strided_ptr &operator+=(difference_type offset) noexcept { data_ += offset * stride_; return *this; } |
| 2848 | strided_ptr &operator-=(difference_type offset) noexcept { data_ -= offset * stride_; return *this; } |
| 2849 | strided_ptr operator+(difference_type offset) const noexcept { strided_ptr temp = *this; return temp += offset; } |
| 2850 | strided_ptr operator-(difference_type offset) const noexcept { strided_ptr temp = *this; return temp -= offset; } |
| 2851 | friend difference_type operator-(strided_ptr const &a, strided_ptr const &b) noexcept { assert(a.stride_ == b.stride_); return (a.data_ - b.data_) / static_cast<difference_type>(a.stride_); } |
| 2852 | friend bool operator==(strided_ptr const &a, strided_ptr const &b) noexcept { return a.data_ == b.data_; } |
| 2853 | friend bool operator<(strided_ptr const &a, strided_ptr const &b) noexcept { return a.data_ < b.data_; } |
| 2854 | friend bool operator!=(strided_ptr const &a, strided_ptr const &b) noexcept { return !(a == b); } |
| 2855 | friend bool operator>(strided_ptr const &a, strided_ptr const &b) noexcept { return b < a; } |
| 2856 | friend bool operator<=(strided_ptr const &a, strided_ptr const &b) noexcept { return !(b < a); } |
| 2857 | friend bool operator>=(strided_ptr const &a, strided_ptr const &b) noexcept { return !(a < b); } |
| 2858 | // clang-format on |
| 2859 | }; |
| 2860 | |
| 2861 | #if defined(__aarch64__) |
| 2862 | /** |
nothing calls this directly
no outgoing calls
no test coverage detected