diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/iterator/mapped.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/iterator/mapped.h')
-rw-r--r-- | library/cpp/iterator/mapped.h | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/library/cpp/iterator/mapped.h b/library/cpp/iterator/mapped.h new file mode 100644 index 0000000000..6c5e763184 --- /dev/null +++ b/library/cpp/iterator/mapped.h @@ -0,0 +1,193 @@ +#pragma once + +#include <util/generic/iterator_range.h> +#include <util/generic/store_policy.h> + +#include <iterator> + + +namespace NIteratorPrivate { + template <class TIterator> + constexpr bool HasRandomAccess() { + return std::is_same_v<typename std::iterator_traits<TIterator>::iterator_category, + std::random_access_iterator_tag>; + } +}; + + +template <class TIterator, class TMapper> +class TMappedIterator { +protected: + using TSelf = TMappedIterator<TIterator, TMapper>; + using TSrcPointerType = typename std::iterator_traits<TIterator>::reference; + using TValue = typename std::invoke_result_t<TMapper, TSrcPointerType>; +public: + using difference_type = std::ptrdiff_t; + using value_type = TValue; + using reference = TValue&; + using pointer = std::remove_reference_t<TValue>*; + using iterator_category = std::conditional_t<NIteratorPrivate::HasRandomAccess<TIterator>(), + std::random_access_iterator_tag, std::input_iterator_tag>; + + TMappedIterator(TIterator it, TMapper mapper) + : Iter(it) + , Mapper(std::move(mapper)) + { + } + + TSelf& operator++() { + ++Iter; + return *this; + } + TSelf& operator--() { + --Iter; + return *this; + } + TValue operator*() { + return Mapper((*Iter)); + } + TValue operator*() const { + return Mapper((*Iter)); + } + + pointer operator->() const { + return &(Mapper((*Iter))); + } + + TValue operator[](difference_type n) const { + return Mapper(*(Iter + n)); + } + TSelf& operator+=(difference_type n) { + Iter += n; + return *this; + } + TSelf& operator-=(difference_type n) { + Iter -= n; + return *this; + } + TSelf operator+(difference_type n) const { + return TSelf(Iter + n, Mapper); + } + TSelf operator-(difference_type n) const { + return TSelf(Iter - n, Mapper); + } + difference_type operator-(const TSelf& other) const { + return Iter - other.Iter; + } + bool operator==(const TSelf& other) const { + return Iter == other.Iter; + } + bool operator!=(const TSelf& other) const { + return Iter != other.Iter; + } + bool operator>(const TSelf& other) const { + return Iter > other.Iter; + } + bool operator<(const TSelf& other) const { + return Iter < other.Iter; + } + +private: + TIterator Iter; + TMapper Mapper; +}; + + +template <class TContainer, class TMapper> +class TInputMappedRange { +protected: + using TContainerStorage = TAutoEmbedOrPtrPolicy<TContainer>; + using TMapperStorage = TAutoEmbedOrPtrPolicy<TMapper>; + using TMapperWrapper = std::reference_wrapper<std::remove_reference_t<TMapper>>; + using TInternalIterator = decltype(std::begin(std::declval<TContainer&>())); + using TIterator = TMappedIterator<TInternalIterator, TMapperWrapper>; +public: + using iterator = TIterator; + using const_iterator = TIterator; + using value_type = typename TIterator::value_type; + using reference = typename TIterator::reference; + using const_reference = typename TIterator::reference; + + TInputMappedRange(TContainer&& container, TMapper&& mapper) + : Container(std::forward<TContainer>(container)) + , Mapper(std::forward<TMapper>(mapper)) + { + } + + TIterator begin() const { + return {std::begin(*Container.Ptr()), {*Mapper.Ptr()}}; + } + + TIterator end() const { + return {std::end(*Container.Ptr()), {*Mapper.Ptr()}}; + } + + bool empty() const { + return std::begin(*Container.Ptr()) == std::end(*Container.Ptr()); + } + +protected: + mutable TContainerStorage Container; + mutable TMapperStorage Mapper; +}; + + +template <class TContainer, class TMapper> +class TRandomAccessMappedRange : public TInputMappedRange<TContainer, TMapper> { + using TBase = TInputMappedRange<TContainer, TMapper>; + using TInternalIterator = typename TBase::TInternalIterator; + using TIterator = typename TBase::TIterator; +public: + using iterator = typename TBase::iterator; + using const_iterator = typename TBase::const_iterator; + using value_type = typename TBase::value_type; + using reference = typename TBase::reference; + using const_reference = typename TBase::const_reference; + + using difference_type = typename std::iterator_traits<iterator>::difference_type; + using size_type = std::size_t; + + TRandomAccessMappedRange(TContainer&& container, TMapper&& mapper) + : TBase(std::forward<TContainer>(container), std::forward<TMapper>(mapper)) + { + } + + using TBase::begin; + using TBase::end; + using TBase::empty; + + size_type size() const { + return std::end(*this->Container.Ptr()) - std::begin(*this->Container.Ptr()); + } + + const_reference operator[](size_t at) const { + Y_ASSERT(at < this->size()); + + return *(this->begin() + at); + } + + reference operator[](size_t at) { + Y_ASSERT(at < this->size()); + + return *(this->begin() + at); + } +}; + +template <class TIterator, class TMapper> +TMappedIterator<TIterator, TMapper> MakeMappedIterator(TIterator iter, TMapper mapper) { + return {iter, mapper}; +} + +template <class TIterator, class TMapper> +auto MakeMappedRange(TIterator begin, TIterator end, TMapper mapper) { + return MakeIteratorRange(MakeMappedIterator(begin, mapper), MakeMappedIterator(end, mapper)); +} + +template <class TContainer, class TMapper> +auto MakeMappedRange(TContainer&& container, TMapper&& mapper) { + if constexpr (NIteratorPrivate::HasRandomAccess<decltype(std::begin(container))>()) { + return TRandomAccessMappedRange<TContainer, TMapper>(std::forward<TContainer>(container), std::forward<TMapper>(mapper)); + } else { + return TInputMappedRange<TContainer, TMapper>(std::forward<TContainer>(container), std::forward<TMapper>(mapper)); + } +} |