简体   繁体   English

为什么在此代码中隐式转换为常量迭代器失败?

[英]Why does implicit conversion to constant iterator fail in this code?

This relates to my previous question here . 这与我之前在这里提出的问题有关。

Here's a summary of that thread: I am trying to implement a doubly-linked-list class called my_list in C++, including iterators and I want automatic implicit conversion of iterator to const_iterator. 这是该线程的摘要:我正在尝试在C ++中实现一个名为my_list的双链表类,其中包括迭代器,并且我希望将迭代器自动隐式转换为const_iterator。

My original thought was to have something like 我最初的想法是拥有类似

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_);}
};

and then inside my_list define iterator as my_list_iterator<T> and const_iterator as my_list_iterator<const T> . 然后在my_list内部将iterator定义为my_list_iterator<T> ,将const_iteratormy_list_iterator<const T>

However, as pointed out by Miled Budneck in the previous thread, this won't work because a pointer to node<T> cannot convert to a pointer to node<const T> . 但是,正如Miled Budneck在上一个线程中指出的那样,这将不起作用,因为指向node<T>的指针无法转换为指向node<const T>的指针。 He suggested I re-implement the const iterator as a pointer to const node instead. 他建议我将const迭代器重新实现为指向const节点的指针。

While that works, by looking around I also found one other possible way to define the iterator class: 在这种情况下,通过环顾四周,我还发现了定义迭代器类的另一种可能方式:

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_);}
};

Then I can define my_list<T>::iterator as my_list_iterator<T,T*,T&> and my_list<T>::const_iterator as my_list_iterator<T,const T*,const T&> . 然后,我可以将my_list<T>::iterator定义为my_list_iterator<T,T*,T&> ,将my_list<T>::const_iteratormy_list_iterator<T,const T*,const T&> I thought the last line would take care of the implicit conversion issue, but it seems to not be used at all. 我认为最后一行将解决隐式转换问题,但似乎根本没有使用它。

For reference, here is the complete code: 作为参考,下面是完整的代码:

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>;
};

and the error message in the end 最后的错误信息

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&>&’

So why does this code not work? 那么为什么这段代码不起作用? Is there any small modification I can make to make it work, or is this design impossible to implement? 我可以做一些小的修改以使其起作用,还是无法实现此设计?

Given Pointer = T* , const Pointer is T* const , not const T* . 给定Pointer = T*const PointerT* const ,而不是const T* Type substitution is not like macro expansion. 类型替换不像宏扩展。 const Pointer adds a top-level const to the type denoted by Pointer . const Pointer增加了顶层 const由表示的类型Pointer Similarly, const Reference is T& const (which is automatically adjusted to T& because top-level cv-qualifiers on references are ignored) instead of const T& . 同样, const ReferenceT& const (会自动调整为T&因为会忽略引用上的顶级cv限定词),而不是const T& (See What is the difference between const int*, const int * const, and int const *? for the difference between T* const and const T* .) (有关T* constconst T* 之间的差异,请参见const int *,const int * const和int const *?有什么区别。)

You need to use something like const std::remove_pointer<Pointer>* for this to work. 您需要使用类似const std::remove_pointer<Pointer>*类的东西才能正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM