2010-05-16 101 views
13

我正在写一个自己的容器类,并遇到了一个问题,我不能得到我的头。这是显示问题的裸骨样本。自己的容器类的C++迭代器和const_iterator问题

它由一个容器类和两个测试类组成:一个测试类使用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: In member function ‘void TestClassMyContainer::test()’:

test2.C:51: error: conversion from ‘MyContainer::iterator’ to non-scalar type ‘MyContainer::const_iterator’ requested

我不知道在哪里,以及为什么编译器要迭代器转换为常量性为我自己的类,但不是为STL向量类。我究竟做错了什么?

回答

9

当您拨打begin()时,编译器默认会创建一个对非const的调用begin()。由于myc不是常量,因此无法知道您的意思是使用常量begin()而非非常量begin()

STL迭代器包含一个演员操作符,它允许iterator被无声地转换为const_iterator。如果你想要这个工作,你需要添加一个,以及像这样:

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

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

或允许const_iterator从一个iterator构造,像这样:

class const_iterator 
{ 
public: 
    typedef const_iterator self_type; 

    const_iterator(iterator&) {} 
    inline const_iterator() { } 
}; 
+0

非常感谢。现在我只需要看看我是否声明const_iterator是迭代器的朋友......或者将访问函数写入私有迭代器成员,但这应该是可行的。 – BaCh 2010-05-16 16:20:50

3

在容器iterator类型必须转换为const_iterator。对于使用非可变(const)迭代器遍历可变容器的情况,这是非常必要的,因为这非常合理。在你的情况下,myc是可变的(非const),但是你创建了一个const迭代器。

+1

这是另一种方式 - '迭代器'必须转换为'const_iterator' – sbk 2010-05-16 17:49:00

+0

对,我混淆了它。 – doublep 2010-05-17 13:53:14

2

你应该看看到升压.Iterator库,尤其是iterator_facadeiterator_adaptor部分。它们包含“从头开始”迭代器的构建。

它会告诉你如何在没有太多重复的情况下编写迭代器,因为除了const限定本身之外,const和non-const版本的代码的大部分时间大致相同。使用模板可以编写一次,然后声明两种不同的类型,这就是库文档说明的内容。