#include <cassert>
#include <memory>
#include <vector>
#include <iostream>
class Range
{
public:
using Index = uint64_t;
using SignedIndex = int64_t;
using Offset = int64_t;
using Size = uint64_t;
Range() = default;
template <typename T>
Range(T start, T end)
{
if (!isValidRange(start, end)) {
assert(false);
return;
}
m_start = start;
m_end = end;
}
Range(const Range& other) = default;
bool isEmpty() const { return 0 == size(); }
bool isValid() const { return isValidRange(m_start, m_end); }
bool isEqual(const Range& other) const { return m_start == other.m_start && m_end == other.m_end; }
bool contains(SignedIndex pos) const { return pos >= 0 && contains((Index)pos); }
bool contains(Index pos) const { return m_start <= pos && pos < m_end; }
bool contains(const Range& other) const
{
return !other.isEmpty() && m_start <= other.m_start && other.m_end <= m_end;
}
Size size() const { return isValid() ? m_end - m_start : 0; }
Index begin() const { return m_start; }
Index start() const { return m_start; }
Index end() const { return m_end; }
Index last() const { return isEmpty() ? m_start : m_end - 1; }
void setSize(Size newSize) { m_end = m_start + newSize; }
bool operator==(const Range& other) const { return isEqual(other); }
bool operator!=(const Range& other) const { return !isEqual(other); }
friend std::ostream& operator<<(std::ostream& os, const Range& range)
{
os << "[" << range.m_start << "," << range.m_end << ")";
return os;
}
protected:
template <typename T>
static bool isValidRange(T start, T end)
{
return start >= 0 && end >= start;
}
private:
Index m_start = 0;
Index m_end = 0;
};
class BidiRange : public Range
{
public:
BidiRange::BidiRange(const Range& range, bool bForward) : Range(range), m_bForward(bForward) {}
[[nodiscard]] bool BidiRange::isForward() const
{
return m_bForward;
}
private:
bool m_bForward;
};
template <typename T>
class VisualIterator
{
public:
using self = T;
using reference = self&;
using pointer = self*;
constexpr explicit VisualIterator(T* ptr, size_t size) : m_node(ptr), m_size(size) {}
constexpr reference operator*() const { return *m_node; }
constexpr pointer operator->() const { return m_node; }
constexpr virtual reference operator++() = 0;
constexpr virtual pointer operator++(int size) = 0;
constexpr virtual reference operator--() = 0;
constexpr virtual pointer operator--(int size) = 0;
[[nodiscard]] constexpr size_t size() const { return m_size; }
constexpr size_t operator-(const VisualIterator<T>& other) const { return m_node - other.operator->(); }
protected:
pointer m_node;
size_t m_size;
};
template <typename T>
using VisualIteratorSp = typename std::shared_ptr<VisualIterator<T>>;
template <typename T>
class ForwardVisualIterator : public VisualIterator<T>
{
public:
using reference = typename VisualIterator<T>::reference;
using pointer = typename VisualIterator<T>::pointer;
constexpr explicit ForwardVisualIterator(T* ptr, size_t size) : VisualIterator<T>(ptr, size) {}
constexpr reference operator++() override
{
++VisualIterator<T>::m_node;
return *VisualIterator<T>::m_node;
}
constexpr pointer operator++(int size) override
{
pointer tmp = VisualIterator<T>::m_node;
tmp += size;
return tmp;
}
constexpr reference operator--() override
{
--VisualIterator<T>::m_node;
return *VisualIterator<T>::m_node;
}
constexpr pointer operator--(int size) override
{
pointer tmp = VisualIterator<T>::m_node;
tmp -= size;
return tmp;
}
};
template <typename T>
class ReverseVisualIterator : public VisualIterator<T>
{
public:
using reference = typename VisualIterator<T>::reference;
using pointer = typename VisualIterator<T>::pointer;
constexpr explicit ReverseVisualIterator(T* ptr, size_t size) : VisualIterator<T>(ptr, size) {}
constexpr reference operator++() override
{
--VisualIterator<T>::m_node;
return *VisualIterator<T>::m_node;
}
constexpr pointer operator++(int size) override
{
pointer tmp = VisualIterator<T>::m_node;
tmp -= size;
return tmp;
}
constexpr reference operator--() override
{
++VisualIterator<T>::m_node;
return *VisualIterator<T>::m_node;
}
constexpr pointer operator--(int size) override
{
pointer tmp = VisualIterator<T>::m_node;
tmp += size;
return tmp;
}
};
/*
template <typename T, template <typename> class VT>
VisualIteratorSp<T> makeVisualIterator(T *ptr, size_t size, bool bBegin)
{
assert(false);
}
*/
template <typename T>
VisualIteratorSp<T> makeVisualIteratorForward(T* ptr, size_t size, bool bBegin)
{
return std::make_shared<ForwardVisualIterator<T>>((bBegin ? ptr : ptr + size), size);
}
template <typename T>
VisualIteratorSp<T> makeVisualIteratorBack(T* ptr, size_t size, bool bBegin)
{
return std::make_shared<ReverseVisualIterator<T>>((bBegin ? ptr + size - 1 : ptr - 1), size);
}
template <typename T>
class BidiVisualIterator
{
public:
using self = T;
using reference = self&;
using pointer = self*;
using BaseVisualIter = VisualIteratorSp<T>;
constexpr explicit BidiVisualIterator(T* ptr, size_t size, bool dir, bool bBegin)
: m_ltr(dir)
, m_iter(dir ? makeVisualIteratorForward<T>(ptr, size, bBegin) : makeVisualIteratorBack<T>(ptr, size, bBegin))
{
}
constexpr reference operator*() const { return m_iter->operator*(); }
constexpr pointer operator->() const { return m_iter->operator->(); }
constexpr reference operator++() { return m_iter->operator++(); }
constexpr pointer operator++(int size) { return m_iter->operator++(size); }
constexpr reference operator--() { return m_iter->operator--(); }
constexpr pointer operator--(int size) { return m_iter->operator--(size); }
constexpr bool operator==(const BidiVisualIterator<T>& other) const
{
return m_ltr == other.m_ltr && operator->() == other.operator->();
}
constexpr bool operator!=(const BidiVisualIterator<T>& other) const { return !operator==(other); }
constexpr size_t operator-(const BidiVisualIterator<T>& other) const
{
return (*m_iter).operator->() - other.operator->();
}
[[nodiscard]] constexpr bool isForward() const { return m_ltr; }
private:
bool m_ltr;
BaseVisualIter m_iter;
};
/*
支持内部双向迭代器rbegin,begin,rend,end
*/
template <typename T>
class BidiVisualSpan : public VisualIterator<T>
{
public:
using reference = typename VisualIterator<T>::reference;
using pointer = typename VisualIterator<T>::pointer;
using cpointer = const typename VisualIterator<T>::self*;
using pointerRef = typename VisualIterator<T>::self*&;
constexpr explicit BidiVisualSpan(const T* ptr, const BidiRange& range)
: VisualIterator<T>(const_cast<T*>(ptr), range.size())
, m_bidiRange(range)
{
}
constexpr BidiVisualIterator<T> begin() const
{
return BidiVisualIterator<T>(VisualIterator<T>::operator->(), VisualIterator<T>::size(), isForward(), true);
}
constexpr BidiVisualIterator<T> end() const
{
return BidiVisualIterator<T>(VisualIterator<T>::operator->(), VisualIterator<T>::size(), isForward(), false);
}
constexpr BidiVisualIterator<T> rbegin() const
{
return BidiVisualIterator<T>(VisualIterator<T>::operator->(), VisualIterator<T>::size(), !isForward(), true);
}
constexpr BidiVisualIterator<T> rend() const
{
return BidiVisualIterator<T>(VisualIterator<T>::operator->(), VisualIterator<T>::size(), !isForward(), false);
}
constexpr BidiVisualIterator<T> last() const
{
BidiVisualIterator<T> tmp = this->end();
--tmp;
return tmp;
}
constexpr pointer operator[](int i) const
{
BidiVisualIterator<T> tmp = this->begin();
auto newNode = tmp.operator++(i);
return newNode;
}
constexpr reference operator++()
{
VisualIterator<T>* base = this;
return base-> operator*();
}
constexpr pointer operator++(int)
{
VisualIterator<T>* base = this;
return base-> operator->();
}
constexpr reference operator--()
{
VisualIterator<T>* base = this;
return base-> operator*();
}
constexpr pointer operator--(int)
{
VisualIterator<T>* base = this;
return base-> operator->();
}
[[nodiscard]] constexpr bool isForward() const { return m_bidiRange.isForward(); }
[[nodiscard]] constexpr const BidiRange& getBidiRange() const { return m_bidiRange; }
constexpr cpointer inc(pointerRef data) const { return const_cast<T*>(isForward() ? ++data : --data); }
constexpr cpointer dec(pointerRef data) const { return const_cast<T*>(isForward() ? --data : ++data); }
constexpr BidiVisualIterator<T> inc(const BidiVisualIterator<T>& data) const
{
auto tmp = data;
++tmp;
return tmp;
}
constexpr BidiVisualIterator<T> dec(const BidiVisualIterator<T>& data) const
{
auto tmp = data;
--tmp;
return tmp;
}
private:
BidiRange m_bidiRange;
};
/**
* @brief 双向迭代器测试
* @return 支持正反序迭代
*/
bool testVisualSpan()
{
std::vector<int> vcts{ 0, 1, 2, 3, 4, 5 };
std::vector<int> expectVct;
// int * start = &vcts[0];
BidiVisualSpan<int> spanVisual(&vcts[0], BidiRange(Range(0, 6), true));
for (auto item = spanVisual.begin(); item != spanVisual.end(); ++item) {
// printf("%d\n", *item);
expectVct.emplace_back(*item);
}
if (expectVct != vcts)
return false;
expectVct.clear();
for (auto item : spanVisual) {
// printf("%d\n", item);
expectVct.emplace_back(item);
}
if (expectVct != vcts)
return false;
expectVct.clear();
for (auto item = spanVisual.rbegin(); item != spanVisual.rend(); ++item) {
// printf("%d\n", *item);
expectVct.emplace_back(*item);
}
std::reverse(expectVct.begin(), expectVct.end());
if (expectVct != vcts)
return false;
expectVct.clear();
BidiVisualSpan<int> spanRVisual(&vcts[0], BidiRange(Range(0, 6), false));
if (spanRVisual.rend() != spanVisual.end())
return false; // 支持双向同源迭代器
if (spanRVisual.rbegin() != spanVisual.begin())
return false; // 支持双向同源迭代器
for (auto item = spanRVisual.begin(); item != spanRVisual.end(); ++item) {
// printf("%d\n", *item);
expectVct.emplace_back(*item);
}
std::reverse(expectVct.begin(), expectVct.end());
if (expectVct != vcts)
return false;
expectVct.clear();
for (auto item : spanRVisual) {
// printf("%d\n", item);
expectVct.emplace_back(item);
}
std::reverse(expectVct.begin(), expectVct.end());
if (expectVct != vcts)
return false;
expectVct.clear();
for (auto item = spanRVisual.rbegin(); item != spanRVisual.rend(); ++item) {
// printf("%d\n", *item);
expectVct.emplace_back(*item);
}
if (expectVct != vcts)
return false;
return true;
}
void test() {
std::cout << (testVisualSpan() ? "Test OK !" : "Test Failed !") << std::endl;
// Test OK !
}
对比参考
std::bidirectional_iterator - cppreference.com