Program Listing for File indexing_iterator.hpp
↰ Return to documentation for file (include/beluga/utility/indexing_iterator.hpp
)
// Copyright 2024 Ekumen, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BELUGA_UTILITY_INDEXING_ITERATOR_HPP
#define BELUGA_UTILITY_INDEXING_ITERATOR_HPP
#include <cstdint>
#include <iterator>
#include <type_traits>
namespace beluga {
template <class Indexable, class Index = typename Indexable::size_type>
class IndexingIterator {
public:
using value_type =
std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Indexable>()[std::declval<Index>()])>>;
using reference = decltype(std::declval<Indexable>()[std::declval<Index>()]);
using pointer = decltype(std::addressof(std::declval<Indexable>()[std::declval<Index>()]));
using difference_type = std::make_signed_t<decltype(std::declval<Index>() - std::declval<Index>())>;
using iterator_category = std::random_access_iterator_tag;
explicit IndexingIterator() = default;
explicit IndexingIterator(Indexable* indexable, Index cursor = Index{})
: indexable_{indexable}, cursor_{std::move(cursor)} {}
explicit IndexingIterator(Indexable& indexable, Index cursor = Index{})
: IndexingIterator(std::addressof(indexable), std::move(cursor)) {}
IndexingIterator operator++(int) noexcept {
IndexingIterator other = *this;
++(*this);
return other;
}
IndexingIterator& operator++() noexcept {
++cursor_;
return *this;
}
IndexingIterator operator--(int) noexcept {
IndexingIterator other = *this;
--(*this);
return other;
}
IndexingIterator& operator--() noexcept {
--cursor_;
return *this;
}
IndexingIterator& operator+=(difference_type offset) noexcept {
using raw_difference_type = decltype(cursor_ - cursor_);
if (offset < 0) {
cursor_ -= static_cast<raw_difference_type>(-offset);
} else {
cursor_ += static_cast<raw_difference_type>(offset);
}
return *this;
}
[[nodiscard]] IndexingIterator operator+(difference_type offset) const noexcept {
IndexingIterator other = *this;
other += offset;
return other;
}
[[nodiscard]] friend IndexingIterator operator+(difference_type offset, const IndexingIterator& iterator) {
return iterator + offset;
}
IndexingIterator& operator-=(difference_type offset) noexcept {
using raw_difference_type = decltype(cursor_ - cursor_);
if (offset < 0) {
cursor_ += static_cast<raw_difference_type>(-offset);
} else {
cursor_ -= static_cast<raw_difference_type>(offset);
}
return *this;
}
[[nodiscard]] IndexingIterator operator-(difference_type offset) const noexcept {
IndexingIterator other = *this;
other -= offset;
return other;
}
[[nodiscard]] difference_type operator-(const IndexingIterator& other) const noexcept {
if (cursor_ < other.cursor_) {
return -static_cast<difference_type>(other.cursor_ - cursor_);
}
return static_cast<difference_type>(cursor_ - other.cursor_);
}
[[nodiscard]] reference operator[](difference_type offset) const noexcept { return (*indexable_)[cursor_ + offset]; }
[[nodiscard]] reference operator*() const noexcept { return (*indexable_)[cursor_]; }
[[nodiscard]] pointer operator->() const noexcept { return std::addressof((*indexable_)[cursor_]); }
bool operator<(const IndexingIterator& other) const noexcept {
return indexable_ == other.indexable_ && cursor_ < other.cursor_;
}
bool operator<=(const IndexingIterator& other) const noexcept {
return indexable_ == other.indexable_ && cursor_ <= other.cursor_;
}
bool operator>(const IndexingIterator& other) const noexcept { return !((*this) <= other); }
bool operator>=(const IndexingIterator& other) const noexcept { return !((*this) < other); }
bool operator==(const IndexingIterator& other) const noexcept {
return indexable_ == other.indexable_ && cursor_ == other.cursor_;
}
bool operator!=(const IndexingIterator& other) const noexcept { return !(*this == other); }
private:
Indexable* indexable_{nullptr};
Index cursor_{};
};
} // namespace beluga
#endif