2010-05-16 225 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版本的代碼的大部分時間大致相同。使用模板可以編寫一次,然後聲明兩種不同的類型,這就是庫文檔說明的內容。