mapped.h 5.8 KB

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