blob: b88a65fc81e3b17fa1b04e9844261c04eea63cb8 (
plain) (
tree)
|
|
#pragma once
#include "store_policy.h"
#include "typetraits.h"
namespace NPrivate {
template <class Range>
class TReverseRangeStorage {
public:
TReverseRangeStorage(Range&& range)
: Base_(std::forward<Range>(range))
{
}
decltype(auto) Base() const {
return *Base_.Ptr();
}
decltype(auto) Base() {
return *Base_.Ptr();
}
private:
TAutoEmbedOrPtrPolicy<Range> Base_;
};
template <class Range>
constexpr bool HasReverseIterators(i32, decltype(std::declval<Range>().rbegin())*) {
return true;
}
template <class Range>
constexpr bool HasReverseIterators(char, std::nullptr_t*) {
return false;
}
template <class Range, bool hasReverseIterators = HasReverseIterators<Range>((i32)0, nullptr)>
class TReverseRangeBase: public TReverseRangeStorage<Range> {
using TBase = TReverseRangeStorage<Range>;
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 Range>
class TReverseRangeBase<Range, false>: public TReverseRangeStorage<Range> {
using TBase = TReverseRangeStorage<Range>;
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 Range>
class TReverseRange: public TReverseRangeBase<Range> {
using TBase = TReverseRangeBase<Range>;
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());
}
};
}
/**
* 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 <class Range>
constexpr ::NPrivate::TReverseRange<Range> Reversed(Range&& range) {
return ::NPrivate::TReverseRange<Range>(std::forward<Range>(range));
}
|