简体   繁体   English

将基于迭代器类的自定义模板对象转换为const_iterator

[英]Convert object of custom template based iterator class to const_iterator

I'm studying OOP course (C++ is a base language) at university. 我正在大学学习OOP课程(C ++是一门基础语言)。 My task is to implement own linked list template container class. 我的任务是实现自己的链表模板容器类。 I did it almost completely but faced with problem. 我几乎完全做到了,但遇到了问题。 It is known that STL provides iterator and const_iterator classes for iteration through list. 众所周知,STL为迭代列表提供了iteratorconst_iterator类。 They have almost the same implementation, the major difference is that iterator's methods return references while const_iterator's methods — constant references. 它们具有几乎相同的实现,主要区别在于迭代器的方法返回引用而const_iterator的方法 - 常量引用。 I followed https://stackoverflow.com/a/3582733/2108548 and created separated template class ListIterator . 我按照https://stackoverflow.com/a/3582733/2108548创建了分离的模板类ListIterator Then I declared with typedef classes Iterator and ConstIterator inside the class List . 然后我在类List使用typedef类声明了IteratorConstIterator

I got something like this: 我有这样的事情:

template<typename T>
class ListNode
{
public:
    ListNode(T *node_value = nullptr, ListNode *node_prev = nullptr, ListNode *node_next = nullptr):
        value(node_value), prev(node_prev), next(node_next) { }

    T *value;
    ListNode *prev, *next;
};

template<typename T>
class ListIterator
{
    typedef ListNode<T> Node;

public:
    ListIterator();
    ListIterator(Node *node);
    ListIterator(ListIterator const &other);
    ListIterator &operator++();
// ...
    Node *i;
};

template<typename T>
class List: public Container
{
    typedef ListIterator<T> Iterator;
    typedef ListIterator<T const> ConstIterator;
// ...
    Iterator begin() const
    {
        return Iterator(m_first->next);
    }
    ConstIterator const_begin() const
    {
        return ConstIterator(begin());
    }
// ...
};

All worked great until I decided to make "copy-constructor" Iterator -> ConstIterator . 一切ConstIterator直到我决定制作“复制构造函数” Iterator - > ConstIterator So I need constructor method that gets ListIterator<T> (where T is the data class name) and creates new object type ListIterator<T const> . 所以我需要构造函数方法获取ListIterator<T> (其中T是数据类名)并创建新的对象类型ListIterator<T const> But in fact ConstIterator 's constructor gets T const as a template parameter, so I need to remove const for constructor's parameter. 但实际上ConstIterator的构造函数将T const作为模板参数,因此我需要删除构造函数参数的const I found header type_traits which does this. 我找到了这样做的头类型type_traits So I wrote "copy-constructor": typedef typename std::remove_cv::type NoConstT; 所以我写了“copy-constructor”:typedef typename std :: remove_cv :: type NoConstT; ListIterator(ListIterator const &other); ListIterator(ListIterator const&other);

But it doesn't work! 但它不起作用! I got this error after requesing const_begin(): 请求const_begin()后我收到此错误:

List<int> list1;
list1 << 1 << 2 << 3;
int i = *list1.const_begin(); 

error: 'ListIterator<T>::ListIterator(const ListIterator<typename std::remove_cv<_Tp>::type>&) [with T = int; typename std::remove_cv<_Tp>::type = int]' cannot be overloaded with 'ListIterator<T>::ListIterator(const ListIterator<T>&) [with T = int; ListIterator<T> = ListIterator<int>]'

But that's not all. 但那还不是全部。 To accomplish my goal have to convert ListNode<T> to ListNode<T const> as well. 要实现我的目标,还必须将ListNode<T>转换为ListNode<T const> But I have one more problem there: each list node contains pointers to previous and next nodes and if I try to initialize them in node's constructor I'll get recursion. 但是我还有一个问题:每个列表节点都包含指向前一个和下一个节点的指针,如果我尝试在节点的构造函数中初始化它们,我将得到递归。 Of course I can create function that handles converting all ListNode<T> nodes to ListNode<T const> by iteration through them. 当然,我可以通过迭代来创建处理将所有ListNode<T>节点转换为ListNode<T const>ListNode<T const> But I don't like this solution: it has huge overhead! 但我不喜欢这个解决方案:它有巨大的开销!

I asked this question my teacher. 我问老师这个问题。 He couldn't understand it for several minutes, then when he got it he said: "It's elementary!" 几分钟他无法理解,然后当他拿到它时说:“这是基本的!” — "But I stuck with it for 3-4 hours!" - “但我坚持了3-4个小时!” — "If so, throw away const iterators and finalize list container without them. I need time to understand your code" (as you see my code is quite simple in my opinion). - “如果是这样,扔掉const迭代器并在没有它们的情况下完成列表容器。我需要时间来理解你的代码”(因为你看我的代码在我看来很简单)。 As I understood he didn't know answer to this question. 据我所知,他不知道这个问题的答案。 But I really want to know how to make it! 但我真的想知道如何制作它! How can I solve this problem? 我怎么解决这个问题?

Sorry for tons of mistakes — I'm not a native English speaker. 对不起大量的错误 - 我不是母语为英语的人。

You can indeed use <type_traits> , just not in the way you describe. 你确实可以使用<type_traits> ,而不是你所描述的方式。 One approach would be to always declare a constructor from the same type and declare from non-const one conditionally with enable_if only when template argument is indeed not constant. 一种方法是始终声明来自相同类型的构造函数,并且仅当模板参数确实不是常量时,才使用enable_if有条件地从非const构造函数声明。 And node should always be non-const, this you can do with remove_const . 并且节点应始终为非const,这可以使用remove_const

#include <type_traits>

template<typename T>
class ListNode
{
   //...   
};

template<typename T>
class ListIterator
{
    typedef ListNode<typename std::remove_const<T>::type> Node;

public:
    ListIterator() {}
    ListIterator(Node*) {}
    ListIterator(ListIterator const&) {}
    template <typename U>
    ListIterator(ListIterator<U> const&, typename std::enable_if<!std::is_const<U>()>::type* = nullptr) {}
};

template<typename T>
class List
{
public:
    typedef ListIterator<T> Iterator;
    typedef ListIterator<T const> ConstIterator;
// ...
    Iterator begin()
    {
        return Iterator(/*...*/);
    }
    ConstIterator const_begin() const
    {
        return ConstIterator(/*...*/);
    }
// ...
};

int main() {
    List<int> list;
    List<int>::ConstIterator ci = list.const_begin(); 
    List<int>::Iterator i = list.begin(); 
    ci = i; // works fine as expected
    i = ci; // fails as expected
    i = i;  // works fine as expected
    ci = ci;  // works fine as expected
    return 0;
}

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

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