【问题标题】:Having trouble implementing a const_iterator for a binary tree C++为二叉树 C++ 实现 const_iterator 时遇到问题
【发布时间】:2022-01-18 00:22:30
【问题描述】:

我正在尝试为我的二叉树实现一个 const_iterator,但是当我尝试编译这个 main 时:

#include "rbtree.hpp"
#include <iostream>

int main(void) {
    rbtree< int >   t;
    t.insert(9);
    t.insert(8);
    t.insert(7);
    t.insert(6);
    t.insert(5);
    t.insert(1);
    t.insert(2);
    t.insert(3);
    t.insert(4);
    for (rbtree< int >::const_iterator it = t.begin(); it != t.end())
        std::cout << *it << std::endl;
    return 0;
}

编译器 (clang++) 输出:

test.cpp:27:37: error: no viable conversion from 'base_iterator<rbtree<int, std::allocator<int>, unsigned long, long>::rbnode>' to 'base_iterator<const rbtree<int, std::allocator<int>, unsigned long, long>::rbnode>'
        for (rbtree< int >::const_iterator it = t.begin(); it != t.end())
                                           ^    ~~~~~~~~~
./rbtree.hpp:172:5: note: candidate constructor not viable: no known conversion from 'rbtree<int, std::allocator<int>, unsigned long, long>::iterator' (aka 'base_iterator<rbtree<int, std::allocator<int>, unsigned long, long>::rbnode>') to 'const rbtree<int, std::allocator<int>, unsigned long, long>::rbnode *' for 1st argument
                                base_iterator(node_type *from) : _ptr(from) { }
                                ^
./rbtree.hpp:173:5: note: candidate constructor not viable: no known conversion from 'rbtree<int, std::allocator<int>, unsigned long, long>::iterator' (aka 'base_iterator<rbtree<int, std::allocator<int>, unsigned long, long>::rbnode>') to 'const rbtree<int, std::allocator<int>, unsigned long, long>::base_iterator<const rbtree<int, std::allocator<int>, unsigned long, long>::rbnode> &' for 1st argument
                                base_iterator(const base_iterator &other) : _ptr(other._ptr) { }
                                ^
1 error generated.

base_iterator 类是rbtree 类的公共类型(rbnode 也是rbtree 的公共类型) 这是我的base_iterator 类的代码:

template <
    typename node_type
> class base_iterator : public std::iterator<
    std::bidirectional_iterator_tag,
    T, // fix, was node_type
    difference_type
> {
    public:
        base_iterator() : _ptr(NULL) { }
        base_iterator(node_type *from) : _ptr(from) { }
        base_iterator(const base_iterator &other) : _ptr(other._ptr) { }
        ~base_iterator() { }

        base_iterator   &operator =(const base_iterator &other) {
            _ptr = other._ptr;
        }
        T               &operator *(void) { return *_ptr->_data; }
        T               *operator ->(void) { return _ptr->_data; }
        base_iterator   &operator ++(void) {
            if (_ptr) {
                if (_ptr->_right) {
                    _ptr = _ptr->_right;
                    while (_ptr->_left) _ptr = _ptr->_left;
                } else {
                    while (
                        _ptr->_parent
                        && _ptr->_parent->_right == _ptr
                    ) _ptr = _ptr->_parent;
                    if (!_ptr->_parent) return base_iterator();
                }
            }
            return _ptr;
        }
        base_iterator   operator ++(int) {
            base_iterator   backup(_ptr);
            ++this;
            return backup;
        }
        base_iterator   &operator --(void) {
            if (_ptr) {
                if (_ptr->_left) {
                    _ptr = _ptr->_left;
                    while (_ptr->_right) _ptr = _ptr->_right;
                } else {
                    while (
                        _ptr->_parent
                        && _ptr->_parent->_left == _ptr
                    ) _ptr = _ptr->_parent;
                    if (!_ptr->_parent) return base_iterator();
                }
            }
            return _ptr;
        }
        base_iterator   operator --(int) {
            base_iterator   backup(_ptr);
            --this;
            return backup;
        }
    private:
        node_type   *_ptr;
};

还有 iteratorconst iterator 的 typedef,以及我的 rbtree 类中的迭代器函数

typedef base_iterator< rbnode >                 iterator;
typedef base_iterator< const rbnode >           const_iterator;
typedef ft::reverse_iterator< iterator >        reverse_iterator;
typedef ft::reverse_iterator< const_iterator >  const_reverse_iterator;

iterator                begin(void) { return iterator(_begin); } // fix, was return _begin;
const_iterator          begin(void) const {
    return const_iterator(_begin);
}
iterator                end(void) { return iterator(); }
const_iterator          end(void) const { return const_iterator(); }
reverse_iterator        rbegin(void) { return iterator(_rbegin); }
const_reverse_iterator  rbegin(void) const {
    return const_iterator(_rbegin);
}
reverse_iterator        rend(void) { return iterator(); }
const_reverse_iterator  rend(void) const { return const_iterator(); }

我还编辑了rbtree类的私有变量:

size_type           _size;
rbnode              *_root;
rbnode              *_begin; // was iterator
rbnode              *_rbegin; // was iterator

所以从技术上讲,这应该可行,为什么不呢?似乎调用了错误的函数(iterator 一个而不是 const_iterator 一个)。 我从您的回答中看到 const 迭代器必须可转换为迭代器?那么这是否意味着我必须为两者使用相同的类型?

【问题讨论】:

  • 我认为您在实现中缺少几个迭代器(注意 const):iterator begin(void) const { return _begin; } iterator end(void) const { return iterator(); } 也就是说,当您的 rbtree 不是 const 但您正在请求常量迭代器。
  • 您将value_type 设置为node_type,但我怀疑您希望它是您在rbtree 中的T。请出示minimal reproducible example,我认为这可以解决。您还有一些不应该编译的东西,例如 ++this;--this;
  • 一个要求是iterator 可以转换为const_iterator。这也是 for 循环中需要的 - begin() 返回一个 iterator
  • @TedLyngmo 谢谢,我会纠正一些事情并重新更新帖子,但我仍然遇到同样的问题
  • 它仍然不是minimal reproducible example,因此必须对您的实现做出很多假设才能指出错误。很容易发现的一个小问题是,您在编辑后仍然使用++this;--this;

标签: c++ class iterator c++98


【解决方案1】:

您必须记住,模板类型是完全独立的。

 base_iterator<X>
 base_iteraotr<const X>

是完全不同的类型。

您的编译器抱怨base_iteraotr&lt;const X&gt; 中没有接受base_iteraotr&lt;X&gt;(完全不同的类型)的构造函数(或转换运算符)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多