diff options
author | pechatnov <pechatnov@yandex-team.ru> | 2022-02-10 16:48:57 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:48:57 +0300 |
commit | 8e9b2f8bbf4a2320f539eef5b85555f42c065425 (patch) | |
tree | 189a13fe5128c85492e45518171a532ffa90ba03 /library/cpp/iterator/zip.h | |
parent | 92040fb3ad117c48c87d591bf9fe916ffda61233 (diff) | |
download | ydb-8e9b2f8bbf4a2320f539eef5b85555f42c065425.tar.gz |
Restoring authorship annotation for <pechatnov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/iterator/zip.h')
-rw-r--r-- | library/cpp/iterator/zip.h | 230 |
1 files changed, 115 insertions, 115 deletions
diff --git a/library/cpp/iterator/zip.h b/library/cpp/iterator/zip.h index ac12ed35fe..6ec0993240 100644 --- a/library/cpp/iterator/zip.h +++ b/library/cpp/iterator/zip.h @@ -1,128 +1,128 @@ -#pragma once - -#include <util/generic/store_policy.h> - -#include <algorithm> -#include <tuple> - - -namespace NPrivate { - - template <typename TContainer, typename TIteratorCategory = typename std::iterator_traits<decltype(std::begin(std::declval<TContainer>()))>::iterator_category> - static constexpr bool HasRandomAccessIterator(int32_t) { - return std::is_same_v<TIteratorCategory, std::random_access_iterator_tag>; - } - - template <typename TContainer> - static constexpr bool HasRandomAccessIterator(uint32_t) { - return false; - } - - template <typename... TContainers> - struct TZipper { - template <std::size_t... I> - struct TZipperWithIndex { - private: - using THolders = std::tuple<TAutoEmbedOrPtrPolicy<TContainers>...>; - using TValue = std::tuple<decltype(*std::begin(std::declval<TContainers&>()))...>; - using TIteratorState = std::tuple<decltype(std::begin(std::declval<TContainers&>()))...>; - using TSentinelState = std::tuple<decltype(std::end(std::declval<TContainers&>()))...>; - - static constexpr bool TrivialSentinel = std::is_same_v<TIteratorState, TSentinelState>; - - struct TIterator; - struct TSentinelCandidate { - TSentinelState Iterators_; - }; - using TSentinel = std::conditional_t<TrivialSentinel, TIterator, TSentinelCandidate>; - -#ifndef _MSC_VER - // windows compiler crashes here - static constexpr bool LimitByFirstContainer = TrivialSentinel && - ((HasRandomAccessIterator<TContainers>(0)) && ...); -#else - static constexpr bool LimitByFirstContainer = false; -#endif - - struct TIterator { - using difference_type = std::ptrdiff_t; - using value_type = TValue; - using pointer = TValue*; - using reference = TValue&; +#pragma once + +#include <util/generic/store_policy.h> + +#include <algorithm> +#include <tuple> + + +namespace NPrivate { + + template <typename TContainer, typename TIteratorCategory = typename std::iterator_traits<decltype(std::begin(std::declval<TContainer>()))>::iterator_category> + static constexpr bool HasRandomAccessIterator(int32_t) { + return std::is_same_v<TIteratorCategory, std::random_access_iterator_tag>; + } + + template <typename TContainer> + static constexpr bool HasRandomAccessIterator(uint32_t) { + return false; + } + + template <typename... TContainers> + struct TZipper { + template <std::size_t... I> + struct TZipperWithIndex { + private: + using THolders = std::tuple<TAutoEmbedOrPtrPolicy<TContainers>...>; + using TValue = std::tuple<decltype(*std::begin(std::declval<TContainers&>()))...>; + using TIteratorState = std::tuple<decltype(std::begin(std::declval<TContainers&>()))...>; + using TSentinelState = std::tuple<decltype(std::end(std::declval<TContainers&>()))...>; + + static constexpr bool TrivialSentinel = std::is_same_v<TIteratorState, TSentinelState>; + + struct TIterator; + struct TSentinelCandidate { + TSentinelState Iterators_; + }; + using TSentinel = std::conditional_t<TrivialSentinel, TIterator, TSentinelCandidate>; + +#ifndef _MSC_VER + // windows compiler crashes here + static constexpr bool LimitByFirstContainer = TrivialSentinel && + ((HasRandomAccessIterator<TContainers>(0)) && ...); +#else + static constexpr bool LimitByFirstContainer = false; +#endif + + struct TIterator { + using difference_type = std::ptrdiff_t; + using value_type = TValue; + using pointer = TValue*; + using reference = TValue&; using const_reference = const TValue&; - using iterator_category = std::input_iterator_tag; - - TValue operator*() { - return {*std::get<I>(Iterators_)...}; - } - TValue operator*() const { - return {*std::get<I>(Iterators_)...}; - } + using iterator_category = std::input_iterator_tag; + + TValue operator*() { + return {*std::get<I>(Iterators_)...}; + } + TValue operator*() const { + return {*std::get<I>(Iterators_)...}; + } TIterator& operator++() { - (++std::get<I>(Iterators_), ...); + (++std::get<I>(Iterators_), ...); return *this; - } + } TIterator operator++(int) { return TIterator{TIteratorState{std::get<I>(Iterators_)++...}}; } - bool operator!=(const TSentinel& other) const { - if constexpr (LimitByFirstContainer) { - return std::get<0>(Iterators_) != std::get<0>(other.Iterators_); - } else { - // yes, for all correct iterators but end() it is a correct way to compare - return ((std::get<I>(Iterators_) != std::get<I>(other.Iterators_)) && ...); - } - } - bool operator==(const TSentinel& other) const { - return !(*this != other); - } - - TIteratorState Iterators_; - }; - public: - using iterator = TIterator; - using const_iterator = TIterator; + bool operator!=(const TSentinel& other) const { + if constexpr (LimitByFirstContainer) { + return std::get<0>(Iterators_) != std::get<0>(other.Iterators_); + } else { + // yes, for all correct iterators but end() it is a correct way to compare + return ((std::get<I>(Iterators_) != std::get<I>(other.Iterators_)) && ...); + } + } + bool operator==(const TSentinel& other) const { + return !(*this != other); + } + + TIteratorState Iterators_; + }; + 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::const_reference; - - TIterator begin() const { - return {TIteratorState{std::begin(*std::get<I>(Holders_).Ptr())...}}; - } - - TSentinel end() const { - if constexpr (LimitByFirstContainer) { - auto endOfFirst = std::begin(*std::get<0>(Holders_).Ptr()) + std::min({ - std::end(*std::get<I>(Holders_).Ptr()) - std::begin(*std::get<I>(Holders_).Ptr())...}); - TIterator iter{TSentinelState{std::end(*std::get<I>(Holders_).Ptr())...}}; - std::get<0>(iter.Iterators_) = endOfFirst; - return iter; - } else { - return {TSentinelState{std::end(*std::get<I>(Holders_).Ptr())...}}; - } - } - - mutable THolders Holders_; - }; - - template <std::size_t... I> - static auto Zip(TContainers&&... containers, std::index_sequence<I...>) { - return TZipperWithIndex<I...>{{std::forward<TContainers>(containers)...}}; - } - }; - -} - - -//! Acts as pythonic zip, BUT result length is equal to shortest length of input containers -//! Usage: for (auto [ai, bi, ci] : Zip(a, b, c)) {...} -template <typename... TContainers> -auto Zip(TContainers&&... containers) { + + TIterator begin() const { + return {TIteratorState{std::begin(*std::get<I>(Holders_).Ptr())...}}; + } + + TSentinel end() const { + if constexpr (LimitByFirstContainer) { + auto endOfFirst = std::begin(*std::get<0>(Holders_).Ptr()) + std::min({ + std::end(*std::get<I>(Holders_).Ptr()) - std::begin(*std::get<I>(Holders_).Ptr())...}); + TIterator iter{TSentinelState{std::end(*std::get<I>(Holders_).Ptr())...}}; + std::get<0>(iter.Iterators_) = endOfFirst; + return iter; + } else { + return {TSentinelState{std::end(*std::get<I>(Holders_).Ptr())...}}; + } + } + + mutable THolders Holders_; + }; + + template <std::size_t... I> + static auto Zip(TContainers&&... containers, std::index_sequence<I...>) { + return TZipperWithIndex<I...>{{std::forward<TContainers>(containers)...}}; + } + }; + +} + + +//! Acts as pythonic zip, BUT result length is equal to shortest length of input containers +//! Usage: for (auto [ai, bi, ci] : Zip(a, b, c)) {...} +template <typename... TContainers> +auto Zip(TContainers&&... containers) { return ::NPrivate::TZipper<TContainers...>::Zip( - std::forward<TContainers>(containers)..., - std::make_index_sequence<sizeof...(TContainers)>{} - ); -} + std::forward<TContainers>(containers)..., + std::make_index_sequence<sizeof...(TContainers)>{} + ); +} |