2011-09-26 3 views
57

STLコンテナの代わりに使用されているコンテナのイテレータを記述しています。現在、STLコンテナは、c++11 foreach syntaxなど多くの場所で使用されています(例:for(auto &x: C))。コードは次のように呼び出すことができているので、私はカスタムコンテナの正しいイテレータを使用するように自動取得するにはどうすればよいC++ 11 foreach構文とカスタムイテレータ

template< typename Type> 
class SomeSortedContainer{ 
    std::vector<typename Type> m_data; //we wish to iterate over this 
    //container implementation code 
};  
class SomeSortedContainerIterator{ 
    //iterator code 
}; 

:我々は、STLコンテナをラップするカスタムクラスを使用するコードを更新する必要がありました方法:?

SomeSortedContainer C; 
for(auto &x : C){ 
    //do something with x... 
} 

一般的に、クラスに正しいイテレータを使用するために必要なものは何ですか?

+0

Visual Studioを使用している場合は、変数の名前の上にマウスを置くと、そのタイプが表示されます。 IIRCでは、 'auto'ではなく、実際のタイプを表示します。 –

答えて

50

次の2つの選択肢があります。

  • あなたはC.begin()C.end()のように呼び出すことができbeginendという名前のメンバ関数を提供します。
  • そうでない場合、あなたは引数依存ルックアップを使用して見つけることができますbeginend命名無料の機能を提供し、または名前空間stdで、かつbegin(C)end(C)のように呼び出すことができます。他の人が述べたよう
+2

["Range-for"ステートメントの詳細については、Stroustrupの[C++ 11 FAQ](http://www.stroustrup.com/C++11FAQ.html)を参照してください(http://www.stroustrup .com/C++ 11FAQ.html#for)(メンバー/機能の優先順位を含む)。 – rluba

50

範囲ベースのを使用できるようにするには、クラスにconst_iterator begin() constconst_iterator end() constのメンバーが必要です。また、グローバルなbegin関数をオーバーロードすることもできますが、メンバー関数を持つことは私の意見では優れています。 iterator begin()およびconst_iterator cbegin() constも推奨されますが、必須ではありません。あなたは、単に単一の内部の容器を反復処理したい場合は、それは本当に簡単です:

template< typename Type> 
class SomeSortedContainer{ 

    std::vector<Type> m_data; //we wish to iterate over this 
    //container implementation code 
public: 
    typedef typename std::vector<Type>::iterator iterator; 
    typedef typename std::vector<Type>::const_iterator const_iterator; 

    iterator begin() {return m_data.begin();} 
    const_iterator begin() const {return m_data.begin();} 
    const_iterator cbegin() const {return m_data.cbegin();} 
    iterator end() {return m_data.end();} 
    const_iterator end() const {return m_data.end();} 
    const_iterator cend() const {return m_data.cend();} 
};  

カスタムかかわらず、何を反復処理したい場合は、おそらくあなたのコンテナ内のクラスとして、独自のイテレータを設計する必要があります。

class const_iterator : public std::iterator<random_access_iterator_tag, Type>{ 
    typename std::vector<Type>::iterator m_data; 
    const_iterator(typename std::vector<Type>::iterator data) :m_data(data) {} 
public: 
    const_iterator() :m_data() {} 
    const_iterator(const const_iterator& rhs) :m_data(rhs.m_data) {} 
    //const iterator implementation code 
}; 

イテレータクラスの作成の詳細については、my answer hereを参照してください。

2

私の知る限りSomeSortedContainerbegin()end()を提供するだけです。そして、あなたのケースではSomeSortedContainerIteratorの標準準拠のフォワードイテレータが返され、実際にはstd::vector<Type>::iteratorがラップされます。標準準拠では、通常のインクリメントと参照解除の演算子を提供する必要があるだけでなく、value_typereference_type、... typedefsもforeach構造体によって使用され、コンテナ要素の基礎となる型を決定します。しかし、あなたはちょうどstd::vector<Type>::iteratorからそれらを転送するかもしれません。

+3

'begin'と' end'メンバ関数がない場合、foreachは 'begin'と' end'非メンバ関数を使うこともできます。 –

+0

@Mike自由な関数がコンテナを単一のパラメータとして扱うことを意味しますか?ニース、私はそれを知らなかった。既存のコンテナクラスを拡張するのに便利だと思います。 –

6

、あなたのコンテナはbegin()end()機能を実装(またはパラメータとしてあなたのコンテナのインスタンスを取るグローバルまたはstd::機能を持っている)必要があります。

これらの関数は同じ型を返さなければなりません(通常はcontainer::iteratorですが、これは慣例に過ぎません)。返される型は、operator*,operator++、およびoperator!=を実装する必要があります。

関連する問題