☰
C++自定义可对称双向迭代器
2026/11/2 1:12:11 网站建设 项目流程
#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


创作不易,小小的支持一下吧!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询