【问题标题】:Why does implicit conversion to constant iterator fail in this code?为什么在此代码中隐式转换为常量迭代器会失败?
【发布时间】:2020-01-03 07:05:38
【问题描述】:

这与我之前的问题here有关。

这是该线程的摘要:我正在尝试在 C++ 中实现一个名为 my_list 的双向链表类,包括迭代器,并且我希望将迭代器自动隐式转换为 const_iterator。

我最初的想法是有类似的东西

template<class T>
class my_list_iterator<T>
{
    node<T> pos_;
    /* code */
    operator my_list_iterator<const T>(){return my_list_iterator<const T>(pos_);}
};

然后在my_list 内部定义iteratormy_list_iterator&lt;T&gt;const_iteratormy_list_iterator&lt;const T&gt;

但是,正如Miled Budneck 在上一个线程中所指出的,这不起作用,因为指向node&lt;T&gt; 的指针无法转换为指向node&lt;const T&gt; 的指针。他建议我将 const 迭代器重新实现为指向 const 节点的指针。

虽然可行,但通过环顾四周,我还发现了另一种定义迭代器类的可能方法:

template<class T, class Pointer, class Reference>
class my_list_iterator {
    node<T>* pos_;
    /* code */
    operator my_list_iterator<T,const Pointer,const Reference>() {return my_list_iterator<T,const Pointer,const Reference>(pos_);}
};

然后我可以将my_list&lt;T&gt;::iterator 定义为my_list_iterator&lt;T,T*,T&amp;&gt; 并将my_list&lt;T&gt;::const_iterator 定义为my_list_iterator&lt;T,const T*,const T&amp;&gt;。我以为最后一行会处理隐式转换问题,但它似乎根本没有使用。

供参考,完整代码如下:

template<class T> class node {
    node(const T& t = T()):data(t),next(0),prev(0) {}
    T data;
    node* next;
    node* prev;

    friend class my_list<T>;
    template<class U,class Pointer,class Reference> friend class my_list_iterator;
};

template<class T,class Pointer,class Reference> class my_list_iterator {
    public:
            // increment and decrement operators
            my_list_iterator operator++();
            my_list_iterator operator++(int);
            my_list_iterator operator--();
            my_list_iterator operator--(int);

            // bool comparison iterators
            bool operator==(const my_list_iterator& other) const {return pos_==other.pos_;}
            bool operator!=(const my_list_iterator& other) const {return pos_!=other.pos_;}

            // member access
            Reference operator*() const {return pos_->data;}
            Pointer operator->() const {return &(pos_->data);}

            // conversion to constant
            operator my_list_iterator<T,const Pointer,const Reference>() {return pos_;}

    private:
            node<T>* pos_;
            explicit my_list_iterator(node<T>* p=0):pos_(p) {}
            friend class my_list<T>;
};

以及最后的错误信息

note:   no known conversion for argument 1 from ‘my_list<int>::iterator’ {aka ‘my_list_iterator<int, int*, int&>’} to ‘const my_list_iterator<int, const int*, const int&>&’

那么为什么这段代码不起作用?是否可以进行任何小的修改以使其正常工作,或者这种设计无法实现?

【问题讨论】:

  • 真实的和预期的模板参数不匹配。
  • 你能扩展一下吗?

标签: c++ iterator doubly-linked-list const-iterator


【解决方案1】:

鉴于Pointer = T*const PointerT* const,而不是const T*。类型替换不像宏扩展。 const Pointer顶级 const 添加到由 Pointer 表示的类型。同样,const ReferenceT&amp; const(它会自动调整为 T&amp;,因为引用上的顶级 cv 限定符被忽略)而不是 const T&amp;。 (T* constconst T* 之间的区别请参见 What is the difference between const int*, const int * const, and int const *?。)

您需要使用const std::remove_pointer&lt;Pointer&gt;* 之类的东西才能使其工作。

【讨论】:

    猜你喜欢
    • 2017-09-18
    • 2022-01-24
    • 2013-01-02
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 2015-02-11
    • 1970-01-01
    相关资源
    最近更新 更多