【问题标题】:Forward Iterator - Const version issue前向迭代器 - 常量版本问题
【发布时间】:2021-05-09 02:28:02
【问题描述】:

我似乎无法解决这个问题。我已经实现了一个模板化的前向迭代器,我还想在我的 ForwardList 类中将它用作 const_iterator。到目前为止我尝试的是使用别名,并插入 const 作为模板参数,但它似乎不起作用。

这是我的前向迭代器:

    template<typename T>
    class forward_iterator {
    private:
        Node<T>* m_iterator;

    public:
        using value_type = T;
        using reference = T&;
        using pointer = value_type*;
        using iterator_category = std::forward_iterator_tag;
        using difference_type = std::ptrdiff_t;

        constexpr forward_iterator(Node<T>* forw_iter) : m_iterator{ forw_iter } {}

        constexpr Node<T>* getNodeAddress() const noexcept { return m_iterator; }
        constexpr Node<T>* getNodeNextAddress() const noexcept { return m_iterator->next; }
        constexpr reference operator*() const noexcept { return m_iterator->data; }
        constexpr pointer operator->() const noexcept { return m_iterator; }
        constexpr forward_iterator& operator++() noexcept {
            m_iterator = m_iterator->next;
            return *this;
        }
        constexpr forward_iterator operator++(int) noexcept {
            forward_iterator tmp(*this);
            m_iterator = m_iterator->next;
            return tmp;
        }
        constexpr friend bool operator== (const forward_iterator& first, const forward_iterator& second) noexcept { return (first.m_iterator == second.m_iterator); }
        constexpr friend bool operator!=(const forward_iterator& first, const forward_iterator& second) noexcept { return !(first.m_iterator == second.m_iterator); }
    };

这就是我在 ForwardList 类中使用别名的方式:

template<typename Type>
    class ForwardList {
    private:
        Node<Type>* m_head;
        Node<Type>* m_tail;
        std::size_t m_size{};       

    public:
        using value_type = Type;
        using size_type = std::size_t;
        using difference_type = std::ptrdiff_t;
        using reference = value_type&;
        using const_reference = const value_type&;
        using pointer = Type*;
        using const_pointer = const pointer;
        using iterator = forward_iterator<value_type>;
        using const_iterator = forward_iterator<const Type>;

这是节点结构:

    template<typename T>
    struct Node {
        T data;
        Node* next;
        Node() = default;
        constexpr explicit Node(const T& data)
            : data{ data } {}
    };

不过,当我使用 const_iterator 时出现错误。例如:

constexpr const_iterator cbegin() const noexcept {
            return const_iterator(m_head);
        }

^ 在迭代器函数中,我得到“Cannot convert from container::Node&lt;Type&gt; *const to container::forward_iterator&lt;const Type&gt;.

另一个例子:

constexpr iterator emplace_after(const_iterator position, Args...args)

^ 在 emplace_after 中,我无法传入普通的“list.begin()”迭代器,因为找不到该函数。我必须改为传递“list.cbegin()”。

如果有人能帮助理解问题所在,那就太好了。

【问题讨论】:

  • 请务必将任何编译器错误也放入代码块中。我不得不编辑您的问题,因为它将 &lt;Type&gt;&lt;const Type&gt; 视为 HTML 块,因此它们只是被忽略而不显示
  • 我没有时间写一个完整的答案,但问题是你不能将Node&lt;Type&gt; 的指针传递给接受Node&lt;const Type&gt;* 指针的函数。就 C++ 而言,不同的模板专业化(甚至只是 CV 认证)是根本不同的类型——因此您需要更改 forward_iterator 的设计方式以适应这种情况
  • using NodeT = std::condition_t&lt;std::is_const_v&lt;Type&gt;,const Node&lt;std::remove_const_t&lt;Type&gt;&gt;, Node&lt;Type&gt;&gt;; 也许?
  • @SomeoneWithPassion works for me
  • 问题是Node&lt;T&gt;无法转换为Node&lt;const T&gt;,所以我使用std::remove_constNode对象的所有设为@ 987654339@

标签: c++ iterator forward-list


【解决方案1】:

以下内容使您的forward_iterator&lt;const T&gt; 指向Node&lt;const T&gt;,而forward_iterator&lt;T&gt; 将指向Node&lt;T&gt;。无论T 是否为const,两者都应指向Node&lt;T&gt;

template<typename T>
class forward_iterator {
private:
    Node<T>* m_iterator;

我发现将迭代器创建为容器类模板中的类模板更容易,这样原始的T 就可用。如果你想在类之外做,你可以在你的迭代器模板中添加一个模板参数:

template<typename OrigT, typename T>
class forward_iterator {
private:
    Node<OrigT>* m_iterator;

public:
    constexpr forward_iterator_impl(Node<OrigT>* forw_iter) : m_iterator{ forw_iter } {}
    ...

并在容器类模板中:

template<typename Type>
class ForwardList {
public:
    ...
    using iterator = forward_iterator<value_type, value_type>;
    using const_iterator = forward_iterator<value_type, const value_type>;

通过将节点和迭代器都移动到容器类中。做对了就变得更容易了。 Demo

【讨论】:

  • 我不知道谁对你投了反对票。正如您发布的那样,我将尝试将其实现为子类。为什么这行得通,将迭代器放在 ForwardList 里面和放在外面有什么区别?谢谢!
  • @SomeoneWithPassion 没有真正的区别,但是因为TIterType 都可用,所以打字更少。请注意,在此实现中 const_iteratoriterator 是不可比较的。不过这很容易解决。
  • 啊,我明白了。事实上,它并没有解决我的两个问题。你有什么想法?谢谢。
  • 嗯,自从我从您的帖子中复制代码后,代码似乎已更改。我一定是在您发布后的最初几分钟内复制了它:-)
  • @SomeoneWithPassion 我进行了更新以使const_iteratoriterator 具有可比性。使用此设置,我在 constexpr const_iterator cbegin() const noexcept { return const_iterator(m_head); } 中没有收到错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-02
  • 1970-01-01
  • 2011-11-15
相关资源
最近更新 更多