【问题标题】:Unable to write my own iterator based on an STL iterator无法基于 STL 迭代器编写我自己的迭代器
【发布时间】:2013-01-19 14:10:54
【问题描述】:

我在尝试基于链表实现容器 Set 时遇到了一点问题。 是的,我知道有一个集合的 STL 实现,但这是家庭作业。 :)

所以,这就是我到目前为止所做的:

我的 Set.h 文件如下所示:

template <class T>
class Set {
private:
    typedef std::list<T> base_container;
    base_container items;
public:
    class myIterator {
    public:
        typename base_container::iterator base_iterator;
        myIterator() { }
    };
    void addItem(const T item) {
        items.push_back(item);
    }
    typedef typename Set<T>::myIterator setIterator;
    setIterator begin() { return items.begin(); }
    setIterator end() { return items.end(); }
    Set<T>(void) { }
    ~Set<T>(void) { }
};

现在,main.cpp:

#include "Set.h"

int main(void) {
    Set<int> mySet;

    mySet.addItem(1);
    mySet.addItem(2);
    mySet.addItem(3);
    mySet.addItem(4);

    Set<int>::myIterator x;
    x = mySet.begin();       // produces an error about non-convertible types.

    return EXIT_SUCCESS;
}

错误如下:

error C2664: 'Set<T>::myIterator::myIterator(const Set<T>::myIterator &)' : cannot convert parameter 1 from 'std::_List_iterator<_Mylist>' to 'const Set<T>::myIterator &' 

显然我把事情搞砸了,但我不确定代码的哪一部分实际上是问题所在。 有关如何解决此问题的任何建议?任何有用的信息将不胜感激。

谢谢。 :)

【问题讨论】:

  • 查看错误信息会有所帮助
  • 哦,是的,当然,抱歉:错误 C2664: 'Set::myIterator::myIterator(const Set::myIterator &)' : cannot convert parameter 1 from ' std::_List_iterator<_mylist>' 到 'const Set::myIterator &'

标签: c++ templates stl iterator


【解决方案1】:

你的方法有很多问题。

正如其他人所说,您不能从基础类型创建迭代器类型:

setIterator begin() { return items.begin(); }
setIterator end() { return items.end(); }

这可以通过向您的类型添加构造函数来解决:

class myIterator {
    typedef typename base_container::iterator base_iterator_type;
public:
    explicit myIterator(base_iterator_type i) : base_iterator(i) { }
    base_iterator_type base_iterator;
    myIterator() { }
};

这个构造函数应该是显式的,这意味着你需要改变你创建它的方式:

setIterator begin() { return setIterator(items.begin()); }

下一个问题是您的类型没有实现迭代器接口,它没有提供operator++operator* 等,也没有定义嵌套类型,例如value_typeiteratory_category,即它不是一个迭代器(只是给它一个带有“迭代器”的名字并不能使它成为真的!)

一旦你解决了这个问题并且你的类型是一个有效的迭代器,你会发现你的容器不能与 STL 风格的算法一起使用,因为它没有实现容器的要求。除此之外,它应该提供一个名为iterator 而不是setIterator 的嵌套类型,以便其他模板代码可以使用S::iterator 而无需关心Sstd::set&lt;T&gt; 还是Set&lt;T&gt;。不要叫它Set&lt;T&gt;::setIterator,就叫它Set&lt;T&gt;::iterator。同样在这种情况下,没有必要定义myIterator(没人关心它是你的!:-) 然后有一个typedef来调用它setIterator,只需首先用正确的名称命名类型,你不需要类型定义。

【讨论】:

    【解决方案2】:

    问题出在这里:

    setIterator begin() { return items.begin(); }
    setIterator end() { return items.end(); }
    

    您尝试返回的值类型错误。它们的类型是base_iterator 而不是setIterator,并且无法从前者隐式转换为后者。

    【讨论】:

    • 好的,那么我怎样才能“提供”一个类似 stl 的迭代器呢?是从 std::iterator 派生的唯一方法吗?
    • @Catalyst:最简单的可能是将底层迭代器封装在您的迭代器中。那么您可能希望考虑在您的迭代器类中使用转换构造函数。
    • @Catalyst 不,您实际上不需要从 std::iterator 继承。它只是一个帮助类,可以免费为您提供一些东西,但您实际上并不需要它来创建与 STL 兼容的迭代器。您只需要公开正确的 typedef,专门化正确的特征,并重载正确的迭代器。
    【解决方案3】:

    您可以从std::iterator&lt;T&gt; 派生并提供适当的迭代器类别标记。这将自动为您的迭代器提供所需的嵌套类型,例如 value_typeT 方面。您仍然需要编写函数成员,例如 operator++operator*(取决于您的迭代器类别,例如,您还需要 operator[] 用于随机访问迭代器)

    【讨论】:

    • 但不会给它operator++operator*
    猜你喜欢
    • 1970-01-01
    • 2011-02-09
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 2013-04-16
    相关资源
    最近更新 更多