mapped.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #pragma once
  2. #include <util/generic/iterator_range.h>
  3. #include <util/generic/store_policy.h>
  4. #include <iterator>
  5. namespace NIteratorPrivate {
  6. template <class TIterator>
  7. constexpr bool HasRandomAccess() {
  8. return std::is_same_v<typename std::iterator_traits<TIterator>::iterator_category,
  9. std::random_access_iterator_tag>;
  10. }
  11. };
  12. template <class TIterator, class TMapper>
  13. class TMappedIterator {
  14. protected:
  15. using TSelf = TMappedIterator<TIterator, TMapper>;
  16. using TSrcPointerType = typename std::iterator_traits<TIterator>::reference;
  17. using TValue = typename std::invoke_result_t<TMapper, TSrcPointerType>;
  18. public:
  19. using difference_type = std::ptrdiff_t;
  20. using value_type = TValue;
  21. using reference = TValue&;
  22. using pointer = std::remove_reference_t<TValue>*;
  23. using iterator_category = std::conditional_t<NIteratorPrivate::HasRandomAccess<TIterator>(),
  24. std::random_access_iterator_tag, std::input_iterator_tag>;
  25. TMappedIterator(TIterator it, TMapper mapper)
  26. : Iter(it)
  27. , Mapper(std::move(mapper))
  28. {
  29. }
  30. TSelf& operator++() {
  31. ++Iter;
  32. return *this;
  33. }
  34. TSelf& operator--() {
  35. --Iter;
  36. return *this;
  37. }
  38. TValue operator*() {
  39. return Mapper((*Iter));
  40. }
  41. TValue operator*() const {
  42. return Mapper((*Iter));
  43. }
  44. pointer operator->() const {
  45. return &(Mapper((*Iter)));
  46. }
  47. TValue operator[](difference_type n) const {
  48. return Mapper(*(Iter + n));
  49. }
  50. TSelf& operator+=(difference_type n) {
  51. Iter += n;
  52. return *this;
  53. }
  54. TSelf& operator-=(difference_type n) {
  55. Iter -= n;
  56. return *this;
  57. }
  58. TSelf operator+(difference_type n) const {
  59. return TSelf(Iter + n, Mapper);
  60. }
  61. TSelf operator-(difference_type n) const {
  62. return TSelf(Iter - n, Mapper);
  63. }
  64. difference_type operator-(const TSelf& other) const {
  65. return Iter - other.Iter;
  66. }
  67. bool operator==(const TSelf& other) const {
  68. return Iter == other.Iter;
  69. }
  70. bool operator!=(const TSelf& other) const {
  71. return Iter != other.Iter;
  72. }
  73. bool operator>(const TSelf& other) const {
  74. return Iter > other.Iter;
  75. }
  76. bool operator<(const TSelf& other) const {
  77. return Iter < other.Iter;
  78. }
  79. private:
  80. TIterator Iter;
  81. TMapper Mapper;
  82. };
  83. template <class TContainer, class TMapper>
  84. class TInputMappedRange {
  85. protected:
  86. using TContainerStorage = TAutoEmbedOrPtrPolicy<TContainer>;
  87. using TMapperStorage = TAutoEmbedOrPtrPolicy<TMapper>;
  88. using TMapperWrapper = std::reference_wrapper<std::remove_reference_t<TMapper>>;
  89. using TInternalIterator = decltype(std::begin(std::declval<TContainer&>()));
  90. using TIterator = TMappedIterator<TInternalIterator, TMapperWrapper>;
  91. public:
  92. using iterator = TIterator;
  93. using const_iterator = TIterator;
  94. using value_type = typename TIterator::value_type;
  95. using reference = typename TIterator::reference;
  96. using const_reference = typename TIterator::reference;
  97. TInputMappedRange(TContainer&& container, TMapper&& mapper)
  98. : Container(std::forward<TContainer>(container))
  99. , Mapper(std::forward<TMapper>(mapper))
  100. {
  101. }
  102. TIterator begin() const {
  103. return {std::begin(*Container.Ptr()), {*Mapper.Ptr()}};
  104. }
  105. TIterator end() const {
  106. return {std::end(*Container.Ptr()), {*Mapper.Ptr()}};
  107. }
  108. bool empty() const {
  109. return std::begin(*Container.Ptr()) == std::end(*Container.Ptr());
  110. }
  111. protected:
  112. mutable TContainerStorage Container;
  113. mutable TMapperStorage Mapper;
  114. };
  115. template <class TContainer, class TMapper>
  116. class TRandomAccessMappedRange : public TInputMappedRange<TContainer, TMapper> {
  117. using TBase = TInputMappedRange<TContainer, TMapper>;
  118. using TInternalIterator = typename TBase::TInternalIterator;
  119. using TIterator = typename TBase::TIterator;
  120. public:
  121. using iterator = typename TBase::iterator;
  122. using const_iterator = typename TBase::const_iterator;
  123. using value_type = typename TBase::value_type;
  124. using reference = typename TBase::reference;
  125. using const_reference = typename TBase::const_reference;
  126. using difference_type = typename std::iterator_traits<iterator>::difference_type;
  127. using size_type = std::size_t;
  128. TRandomAccessMappedRange(TContainer&& container, TMapper&& mapper)
  129. : TBase(std::forward<TContainer>(container), std::forward<TMapper>(mapper))
  130. {
  131. }
  132. using TBase::begin;
  133. using TBase::end;
  134. using TBase::empty;
  135. size_type size() const {
  136. return std::end(*this->Container.Ptr()) - std::begin(*this->Container.Ptr());
  137. }
  138. const_reference operator[](size_t at) const {
  139. Y_ASSERT(at < this->size());
  140. return *(this->begin() + at);
  141. }
  142. reference operator[](size_t at) {
  143. Y_ASSERT(at < this->size());
  144. return *(this->begin() + at);
  145. }
  146. };
  147. template <class TIterator, class TMapper>
  148. TMappedIterator<TIterator, TMapper> MakeMappedIterator(TIterator iter, TMapper mapper) {
  149. return {iter, mapper};
  150. }
  151. template <class TIterator, class TMapper>
  152. auto MakeMappedRange(TIterator begin, TIterator end, TMapper mapper) {
  153. return MakeIteratorRange(MakeMappedIterator(begin, mapper), MakeMappedIterator(end, mapper));
  154. }
  155. template <class TContainer, class TMapper>
  156. auto MakeMappedRange(TContainer&& container, TMapper&& mapper) {
  157. if constexpr (NIteratorPrivate::HasRandomAccess<decltype(std::begin(container))>()) {
  158. return TRandomAccessMappedRange<TContainer, TMapper>(std::forward<TContainer>(container), std::forward<TMapper>(mapper));
  159. } else {
  160. return TInputMappedRange<TContainer, TMapper>(std::forward<TContainer>(container), std::forward<TMapper>(mapper));
  161. }
  162. }