14

我正在编写一个自己的容器类并且遇到了一个我无法理解的问题。这是显示问题的简单示例。

它由一个容器类和两个测试类组成:一个使用 std:vector 的测试类可以很好地编译,第二个测试类尝试以完全相同的方式使用我自己的容器类,但编译失败。

#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename T>
class MyContainer
{
public:
  
  class iterator
  {
  public:
    typedef iterator self_type;
    inline iterator() { }
  };

  class const_iterator
  {
  public:
    typedef const_iterator self_type;
    inline const_iterator() { }
  };
  
  iterator begin() {
    return iterator();
  }

  const_iterator begin() const {
    return const_iterator();
  }
};

// This one compiles ok, using std::vector
class TestClassVector
{
public:
  void test() {
    vector<int>::const_iterator I=myc.begin();
  }

private:
  vector<int> myc;
};

// this one fails to compile. Why?
class TestClassMyContainer
{
public:
  void test(){
    MyContainer<int>::const_iterator I=myc.begin();
  }

private:
  MyContainer<int> myc;
};


int main(int argc, char ** argv)
{
  return 0;
}

gcc 告诉我:

test2.C:在成员函数'void TestClassMyContainer::test()'中:

test2.C:51:错误:请求从“MyContainer::iterator”转换为非标量类型“MyContainer::const_iterator”

我不确定编译器在哪里以及为什么要将迭代器转换为我自己的类的 const_iterator,而不是 STL 向量类。我究竟做错了什么?

4

3 回答 3

10

默认情况下,当您调用begin()编译器时,会创建对 non-const 的调用begin()。由于myc不是 const,它无法知道您的意思是使用 constbegin()而不是 non-const begin()

STL 迭代器包含一个强制转换运算符,它允许将iteratora 静默转换为 a const_iterator。如果你想让它工作,你需要像这样添加一个:

class iterator
{
public:
    typedef iterator self_type;
    inline iterator() { }

    operator const_iterator() { return const_iterator(); }
};

或允许const_iteratoriterator类似的构造:

class const_iterator
{
public:
    typedef const_iterator self_type;

    const_iterator(iterator& ) {}
    inline const_iterator() { }
};
于 2010-05-16T15:57:03.987 回答
3

你应该看看 Boost.Iterators 库,尤其是iterator_facadeanditerator_adaptor部分。它们包含“从头开始”构建的迭代器。

它将向您展示如何在没有太多重复的情况下编写迭代器,因为除了const限定本身之外,大多数时候 const 和非 const 版本的代码大致相同。使用模板可以编写一次,然后声明两种不同的类型,这就是库文档说明的内容。

于 2010-05-17T06:29:52.210 回答
3

在容器中iterator类型必须可转换为const_iterator. 在使用非可变(const)迭代器迭代可变容器的情况下,这是必需的,因为这非常有意义。在您的情况下myc是可变的(非常量),但是您在其上创建了一个 const 迭代器。

于 2010-05-16T15:54:04.603 回答