[英]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_iterator
为my_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_iterator
为my_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 Pointer
是T* 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 Reference
是T& 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* const
和const 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.