【问题标题】:Bidirectional iterator implementation双向迭代器实现
【发布时间】:2019-10-31 20:51:13
【问题描述】:

由于某些原因,我需要实现一个双向迭代器,一段时间后,我得到了这个结果(add 参数告诉迭代器应该移动到哪一侧(为了避免代码重复,在实现 reverse_iterator 时)):

#include <iterator>

namespace gph {
    template <typename T, int add> class BidirectionalIterator;

    template<typename T, int add>
    void swap(BidirectionalIterator<T, add>& it1, BidirectionalIterator<T, add>& it2) {
        it1.swap(it2);
    }

    template<typename T, int add>
    class BidirectionalIterator {
    private:
        T *currentPosition, *begin, *end;
    public:
        using difference_type = std::ptrdiff_t;
        using value_type = T;
        using pointer = T*;
        using reference = T&;
        using iterator_category = std::bidirectional_iterator_tag;

        inline BidirectionalIterator(T* currentPosition, T* begin, T* end):currentPosition(currentPosition), begin(begin), end(end) {}

        //copy constructor
        inline BidirectionalIterator(const BidirectionalIterator& iterator)
            :BidirectionalIterator(iterator.currentPosition, iterator.begin, iterator.end) {}

        //move constructor
        inline BidirectionalIterator(BidirectionalIterator&& iterator) noexcept
            :BidirectionalIterator(iterator.currentPosition, iterator.begin, iterator.end) {}

        //copy and move assignment statement
        inline BidirectionalIterator& operator=(BidirectionalIterator iterator) {
           gph::swap(*this, iterator);
        }

        inline void swap(BidirectionalIterator& iterator) {
            std::swap(currentPosition, iterator.currentPosition);
            std::swap(begin, iterator.begin);
            std::swap(end, iterator.end);
        }

        inline reference operator*() const {
            return *currentPosition; //dangerous if the iterator is in not-dereferenceable state
        }

        inline BidirectionalIterator& operator++() {
            if (currentPosition != end) currentPosition += add;

            return *this;
        }

        inline bool operator==(const BidirectionalIterator& iterator) const {
            return currentPosition == iterator.currentPosition;
        }

        inline bool operator!=(const BidirectionalIterator& iterator) const {
            return !(*this == iterator);
        }

        inline BidirectionalIterator operator++(int) {
            BidirectionalIterator past = *this;

            ++*this;

            return past;
        }

        inline BidirectionalIterator& operator--() {
            if (currentPosition != begin) currentPosition -= add;

            return *this;
        }

        inline BidirectionalIterator operator--(int) {
            BidirectionalIterator past = *this;

            --*this;

            return past;
        }
    };
}

我已经尝试满足MoveAssignableMoveConstructibleCopyAssignableCopyConstructibleSwappableEqualityComparableLegacyIteratorLegacyInputIteratorLegacyForwardIterator、@98765434 命名要求.

他们的一些需求体现在操作符重载中,但其中一些我不知道如何实现(也许它们是由其他人自动实现的?),例如:i-&gt;m*i++(来自here)。第一个问题:我应该如何实现它们?

第二个问题:我的迭代器实现好吗?它有什么缺点,我哪里出错了?

附:这些问题处于非建设性的边缘,但我真的需要帮助。对不起我的英语。

【问题讨论】:

    标签: c++


    【解决方案1】:

    我发现很难找到一个明确的答案,所以只是一些想法,可能不完整,可以讨论。

    • i-&gt;m可以通过inline pointer operator-&gt;() { return this-&gt;currentPosition; }实现
    • *i++ 应该已经包含在您的实现中
    • 我看不出有任何理由交换operator= 中的所有指针。三个原因:

      1. 您正在用局部变量交换值
      2. 移动构造函数不交换任何值(BidirectionalIterator newIt=oldIt;BidirectionalIterator newIt(oldIt); 之间的行为会不一致,但实际上不是因为前一点)
      3. 那些指针不是唯一资源,所以复制它们并在多个实例之间共享它们是没有问题的
    • operator= 缺少 return
    • 你有using difference_type = std::ptrdiff_t;,但没有实现operator-,它会返回difference_type,为什么不实现呢?
    • std::reverse_iterator 可以更轻松地实现反向迭代器,它只会包装您的迭代器并反转 ++ 和 -- 等等。
    • 您可能希望找到一种简单的方法来实现迭代器的 const 版本(始终返回 const T&amp;const T* 的版本)。我看到了这个的三个版本:
      • 复制所有代码
      • 使用const cast
      • 使用附加模板参数bool TIsConstusing pointer = std::conditional_t&lt;TIsConst, const T*, T*&gt;;
      • 另一方面,使用带有参数const T 的模板化迭代器可能看起来很容易,但无法满足要求see this question

    【讨论】:

    • 我认为我可以通过将 const char 传递给模板来实现 const 迭代器。我可以这样做吗?
    • 另外,我正在用局部变量交换指针,因为我正在实现复制和交换习语,所以局部变量就是那个副本
    • @wcobalt 赋值时,复制赋值的右侧(使用复制构造函数),然后用一些局部变量交换值。但是局部变量会超出范围,= 的原始 rhs 将保持不变。所以整个交换在那里是不必要的。基本上与复制值相同。
    • @wcobalt 至于基本上使用 const T 作为模板参数的想法 - 我不确定 为什么 这没有完成,但肯定有一些问题有了它,由于您在任何地方都找不到这种模式,我将对此进行一些研究。
    • " 分配时,您复制右侧..." 但是如果在移动构造函数中我会进行交换,那么一切都会好起来的,对吧?
    猜你喜欢
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    相关资源
    最近更新 更多