首页 > 编程语言 >C++自定义双向迭代器

C++自定义双向迭代器

时间:2024-07-16 19:25:16浏览次数:18  
标签:return 迭代 自定义 C++ constexpr operator const VisualIterator size


#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


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

标签:return,迭代,自定义,C++,constexpr,operator,const,VisualIterator,size
From: https://blog.csdn.net/qq_30220519/article/details/140474687

相关文章

  • C++(3) 3D-3D ICP SVD RANSCE
    CMakeLists.txtcmake_minimum_required(VERSION3.5)project(ICP_SVD_example)#SetC++standardtoC++11set(CMAKE_CXX_STANDARD11)set(CMAKE_CXX_STANDARD_REQUIREDON)#FindEigenlibraryfind_package(Eigen3REQUIRED)#IncludedirectoriesforEigeni......
  • 不动点迭代法
    不动点迭代(Fixed-pointiteration)(不动点) $x$为单值算子$\mathbb{T}$的不动点,如果$$\mathbb{T}x=x$$ 记$\text{Fix}\mathbb{T}=\{x|x=\mathbb{T}x\}=(\mathbb{I}-\mathbb{T})^{-1}(0)$为单值算子$\mathbb{T}$的不动点集合。 如果单值算子$\mathbb{T}$是非扩张的且$\text{d......
  • GESP C++ 三级真题(2023年6月)密码合规
    【问题描述】网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求:1、只能由a-z之间26个小写字母、A-Z之间26个大写字母、0-9之间10个数字以及!@#$四个特殊字符构成。2、密码最短长度:6个字符,密码最大长度:12个字......
  • 自定义localStorage监听事件
    一、问题在项目开发过程中,发现有很多时候进行localStorage.setItem()操作设置本地存储后,页面必须刷新才能够获取到存储数据,而有些时候本地缓存更新后,页面无法通过再次刷新以获取本地缓存,这就导致依赖本地缓存的数据无法进行更新。为了解决这个问题,就必须要用到自定义localStorage......
  • C++(函数参数为数组与指针算术)
    目录1.函数参数为数组2.指针算术2.1arr是指向第一个元素的地址2.2arr[i]表示什么?#include<iostream>voidprintArray(intarr[],intsize){for(inti=0;i<size;++i){std::cout<<arr[i]<<"";}}intmain(){intarr[5]......
  • C++题解(7) 信息学奥赛一本通:1055:判断闰年
    【题目描述】判断某年是否是闰年。如果公元a年是闰年输出Y,否则输出N。【输入】输入只有一行,包含一个整数a(0<a<3000)。【输出】一行,如果公元a年是闰年输出Y,否则输出N。【输入样例】2006【输出样例】N【知识链接:如何判断闰年】(1)能被4整除,但不......
  • C++题解(6) 信息学奥赛一本通:2069:【例2.12 】糖果游戏
    【题目描述】某幼儿园里,有5个小朋友编号为1、2、3、4、5,他们按自己的编号顺序围坐在一张圆桌旁。他们身上都有若干个糖果(键盘输入),现在他们做一个分糖果游戏。从1号小朋友开始,将自己的糖果均分三份(如果有多余的糖果,则立即吃掉),自己留一份,其余两份分给他的相邻的两个小朋友。......
  • 【C++】链表相关的项目(2.0)
    链表相关的项目1.0需要请点击       ---------------------------------------------------准备工作首先弄几个可能会需要的头文件:#include<stdio.h>#include<stdlib.h>#include<string.h>typedefintADT;//定义自定义数据类型​​因为写的是关于......
  • C++11平凡可复制类型检测is_trivially_copyable
    1.C++基础回顾     在C++11中,平凡类型(TrivialType)、平凡可复制类型(TrivialCopyable)、标准布局类型(Standard-layoutType)是描述类在内存中布局特性的术语,它们与类的构造、拷贝、赋值和销毁行为有关,也影响着类的内存布局和对齐方式。下面用通俗的语言解释这些概念:1.1.平......
  • C++获取当前毫秒数
    转自https://www.cnblogs.com/c9080/p/17509268.html,在C++11中,可以使用<chrono>头文件中的std::chrono::system_clock类来获取当前时间戳。它提供了多种精度和分辨率的时钟类型,其中最常用的是系统时钟。以下是一个示例程序,演示如何使用std::chrono::system_clock类获取......