#pragma once #include "store_policy.h" #include "typetraits.h" namespace NPrivate { template class TReverseRangeStorage { public: TReverseRangeStorage(Range&& range) : Base_(std::forward(range)) { } decltype(auto) Base() const { return *Base_.Ptr(); } decltype(auto) Base() { return *Base_.Ptr(); } private: TAutoEmbedOrPtrPolicy Base_; }; template constexpr bool HasReverseIterators(i32, decltype(std::declval().rbegin())*) { return true; } template constexpr bool HasReverseIterators(char, std::nullptr_t*) { return false; } template ((i32)0, nullptr)> class TReverseRangeBase: public TReverseRangeStorage { using TBase = TReverseRangeStorage; public: using TBase::Base; using TBase::TBase; auto begin() const { return Base().rbegin(); } auto end() const { return Base().rend(); } auto begin() { return Base().rbegin(); } auto end() { return Base().rend(); } }; template class TReverseRangeBase: public TReverseRangeStorage { using TBase = TReverseRangeStorage; public: using TBase::Base; using TBase::TBase; auto begin() const { using std::end; return std::make_reverse_iterator(end(Base())); } auto end() const { using std::begin; return std::make_reverse_iterator(begin(Base())); } auto begin() { using std::end; return std::make_reverse_iterator(end(Base())); } auto end() { using std::begin; return std::make_reverse_iterator(begin(Base())); } }; template class TReverseRange: public TReverseRangeBase { using TBase = TReverseRangeBase; public: using TBase::Base; using TBase::TBase; TReverseRange(TReverseRange&&) = default; TReverseRange(const TReverseRange&) = default; auto rbegin() const { using std::begin; return begin(Base()); } auto rend() const { using std::end; return end(Base()); } auto rbegin() { using std::begin; return begin(Base()); } auto rend() { using std::end; return end(Base()); } }; } // namespace NPrivate /** * Provides a reverse view into the provided container. * * Example usage: * @code * for(auto&& value: Reversed(container)) { * // use value here. * } * @endcode * * @param cont Container to provide a view into. Must be an lvalue. * @returns A reverse view into the provided container. */ template constexpr ::NPrivate::TReverseRange Reversed(Range&& range) { return ::NPrivate::TReverseRange(std::forward(range)); }