adaptor.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #pragma once
  2. #include "store_policy.h"
  3. #include "typetraits.h"
  4. namespace NPrivate {
  5. template <class Range>
  6. class TReverseRangeStorage {
  7. public:
  8. TReverseRangeStorage(Range&& range)
  9. : Base_(std::forward<Range>(range))
  10. {
  11. }
  12. decltype(auto) Base() const {
  13. return *Base_.Ptr();
  14. }
  15. decltype(auto) Base() {
  16. return *Base_.Ptr();
  17. }
  18. private:
  19. TAutoEmbedOrPtrPolicy<Range> Base_;
  20. };
  21. template <class Range>
  22. constexpr bool HasReverseIterators(i32, decltype(std::declval<Range>().rbegin())*) {
  23. return true;
  24. }
  25. template <class Range>
  26. constexpr bool HasReverseIterators(char, std::nullptr_t*) {
  27. return false;
  28. }
  29. template <class Range, bool hasReverseIterators = HasReverseIterators<Range>((i32)0, nullptr)>
  30. class TReverseRangeBase: public TReverseRangeStorage<Range> {
  31. using TBase = TReverseRangeStorage<Range>;
  32. public:
  33. using TBase::Base;
  34. using TBase::TBase;
  35. auto begin() const {
  36. return Base().rbegin();
  37. }
  38. auto end() const {
  39. return Base().rend();
  40. }
  41. auto begin() {
  42. return Base().rbegin();
  43. }
  44. auto end() {
  45. return Base().rend();
  46. }
  47. };
  48. template <class Range>
  49. class TReverseRangeBase<Range, false>: public TReverseRangeStorage<Range> {
  50. using TBase = TReverseRangeStorage<Range>;
  51. public:
  52. using TBase::Base;
  53. using TBase::TBase;
  54. auto begin() const {
  55. using std::end;
  56. return std::make_reverse_iterator(end(Base()));
  57. }
  58. auto end() const {
  59. using std::begin;
  60. return std::make_reverse_iterator(begin(Base()));
  61. }
  62. auto begin() {
  63. using std::end;
  64. return std::make_reverse_iterator(end(Base()));
  65. }
  66. auto end() {
  67. using std::begin;
  68. return std::make_reverse_iterator(begin(Base()));
  69. }
  70. };
  71. template <class Range>
  72. class TReverseRange: public TReverseRangeBase<Range> {
  73. using TBase = TReverseRangeBase<Range>;
  74. public:
  75. using TBase::Base;
  76. using TBase::TBase;
  77. TReverseRange(TReverseRange&&) = default;
  78. TReverseRange(const TReverseRange&) = default;
  79. auto rbegin() const {
  80. using std::begin;
  81. return begin(Base());
  82. }
  83. auto rend() const {
  84. using std::end;
  85. return end(Base());
  86. }
  87. auto rbegin() {
  88. using std::begin;
  89. return begin(Base());
  90. }
  91. auto rend() {
  92. using std::end;
  93. return end(Base());
  94. }
  95. };
  96. }
  97. /**
  98. * Provides a reverse view into the provided container.
  99. *
  100. * Example usage:
  101. * @code
  102. * for(auto&& value: Reversed(container)) {
  103. * // use value here.
  104. * }
  105. * @endcode
  106. *
  107. * @param cont Container to provide a view into. Must be an lvalue.
  108. * @returns A reverse view into the provided container.
  109. */
  110. template <class Range>
  111. constexpr ::NPrivate::TReverseRange<Range> Reversed(Range&& range) {
  112. return ::NPrivate::TReverseRange<Range>(std::forward<Range>(range));
  113. }