为不返回真实基础类型的迭代器实现运算符>

Implementing operator-> for an iterator that does not return the true underlying type

提问人:dw218192 提问时间:4/8/2023 更新时间:4/8/2023 访问量:70

问:

假设我想为一个表示 2D 点数组的类实现迭代器。 迭代器应该使类看起来像是存储了一对双精度值的数组,但该类实际上使用了 2 个单独的数组(一个用于 X 坐标,一个用于 Y 坐标)。我想知道我应该如何实现迭代器。我当然不能从中获取返回值的地址,因为它是一个临时值。我应该在每次调用时在堆上分配一个吗?有没有好办法?operator->()operator*pair<double&, double&>operator->()

struct PointArray {
    std::vector<double> m_x;
    std::vector<double> m_y;

    // Define a custom iterator class for ControlPointArray
    class iterator {
    public:
        using value_type = std::pair<double&, double&> const;
        using reference = value_type;
        using pointer = value_type*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::random_access_iterator_tag;

        iterator() = default;
        iterator(const typename std::vector<double>::iterator& x_it, const typename std::vector<double>::iterator& y_it)
            : m_x_it(x_it), m_y_it(y_it) {}

        reference operator*() const { return { *m_x_it, *m_y_it }; }
        pointer operator->() const {
            // how to implement this method ??
        }

        iterator& operator++() { ++m_x_it; ++m_y_it; return *this; }
        iterator operator++(int) { auto copy = *this; ++(*this); return copy; }
        iterator& operator--() { --m_x_it; --m_y_it; return *this; }
        iterator operator--(int) { auto copy = *this; --(*this); return copy; }
        iterator& operator+=(difference_type n) { m_x_it += n; m_y_it += n; return *this; }
        iterator operator+(difference_type n) const { auto copy = *this; copy += n; return copy; }
        iterator& operator-=(difference_type n) { return (*this) += -n; }
        iterator operator-(difference_type n) const { auto copy = *this; copy -= n; return copy; }
        difference_type operator-(const iterator& other) const { return m_x_it - other.m_x_it; }
        reference operator[](difference_type n) const { return *(*this + n); }
        bool operator==(const iterator& other) const { return m_x_it == other.m_x_it; }
        bool operator!=(const iterator& other) const { return !(*this == other); }
        bool operator<(const iterator& other) const { return m_x_it < other.m_x_it; }
        bool operator<=(const iterator& other) const { return m_x_it <= other.m_x_it; }
        bool operator>(const iterator& other) const { return m_x_it > other.m_x_it; }
        bool operator>=(const iterator& other) const { return m_x_it >= other.m_x_it; }

    private:
        typename std::vector<double>::iterator m_x_it;
        typename std::vector<double>::iterator m_y_it;
    };

    // Define begin() and end() functions to return iterators
    iterator begin() { return { m_x.begin(), m_y.begin() }; }
    iterator end() { return { m_x.end(), m_y.end() }; }

// the rest of the PointArray class...
};
C++ 迭代器

评论

0赞 Adrian Mole 4/8/2023
重载或实现自定义是一件棘手的事情。请注意,从这个答案中可以看出,您自己的不是调用,而是(而是)使用了内置的取消引用。不确定这是否是你的问题,不过......只是说'。operator->()operator*
0赞 Mooing Duck 4/8/2023
如果走这条路,就没有理由进行堆分配。您可以简单地按值返回它pair<double&, double&>
0赞 Adrian Mole 4/8/2023
@MooingDuck我认为这必须返回一个指针,或者至少是一个伪指针类型。另请参阅此规范答案的最后一部分。operator->()
0赞 Mooing Duck 4/8/2023
@AdrianMole你是对的,我不得不停下来,更努力地思考一下。我制定了细节,但现在已将它们作为答案发布。

答:

2赞 Mooing Duck 4/8/2023 #1

返回一个伪指针,该伪指针本身包含这些值。

struct pseudo_pointer {
   value pair_of_data;
   pointer operator->() const {return &pair_of_data;}
};

pseudo_pointer operator->() const {
    return pseudo_pointer{{ *m_x_it, *m_y_it }};
}

这是我脑海中的伪代码,可能需要进一步调整才能编译

评论

1赞 Mooing Duck 4/8/2023
如果我没记错的话,我之所以学会这个,是因为我试图弄清楚它是如何实现的,然后不得不阅读它 4 遍才能弄清楚那里发生了什么std::vector<bool>::iterator::operator->()