2011-10-19 11 views
6

、このようなコードがあります:ラップSTLベクトルとその反復子の動作を変更

#include <iostream> 
#include <vector> 

template <class T> 
class A{ 
public: 
    class iterator : public std::vector<T>::iterator{ 
    public: 
     T& operator*(){ 
      ?? 
     } 
    }; 

    iterator begin(){ 
     return v.begin(); // error 
    } 

    iterator end(){ 
     return v.end(); // error 
    } 

    void add(const T& elem){ 
     v.push_back(elem); 
    } 

private: 
    std::vector<T> v; 
}; 

int main() { 
    A<int> a; 
    a.add(2); 
    a.add(4); 
    for(A<int>::iterator it = a.begin(); it != a.end(); ++it){ 
     std::cout << *it << std::endl; 
    } 
    return 0; 
} 

これは私自身の追加機能を持つstd::vectorのラッパーです。

T& operator*(){ 
    // do some additional function 
    // normal behavior, return value of some element in vector 
      ?? 
} 

は、どのように私はoperator*の変更でstd::vectorし、そのイテレータを使用することができます?私は、しかし、私は唯一のイテレータのためoperator*の動作を変更したい、std::vectorの反復子を使用したいですか私はイテレータのためにbegin()end()のような関数をラップしたいと思います。どのように正しくラップするのですか?

EDIT:

は、このトピックで回答からヒントを使用して、私は道を次のように私の問題を解決するために管理:

#include <iostream> 
#include <vector> 

template <class T> 
class A { 
public: 

    class iterator : public std::vector<T>::iterator { 
    public: 

     iterator(typename std::vector<T>::iterator c) : std::vector<T>::iterator(c) { 
     } 

     T& operator*() { 
      std::cout << "Im overloaded operator*\n"; 
      return std::vector<T>::iterator::operator *(); 
     } 
    }; 

    iterator begin() { 
     return iterator(v.begin()); 
    } 

    iterator end() { 
     return iterator(v.end()); 
    } 

    void add(const T& elem) { 
     v.push_back(elem); 
    } 

private: 
    std::vector<T> v; 
}; 

int main() { 
    A<int> a; 
    a.add(2); 
    a.add(4); 

    for (A<int>::iterator it = a.begin(); it != a.end() ; ++it) { 
     std::cout << *it << std::endl; 
    } 
    return 0; 
} 

多分それが誰かのために参考になります。

+0

私はコードを誤解した。それがどう起こったのか分かりません。 –

答えて

3

stdlibイテレーターのラッピングは、イテレーターアダプターで最も効果的です。この作業は簡単ではありません。作業を簡略化するためにBoost.Iteratorライブラリがあります。すでに提供されているイテレータのうちの1つがすでにあなたの問題を解決しているかもしれません。あなたは(私は本当にがこれをお勧めしません)自分でこれを書いしようとしている場合

、あなたがあなた自身のイテレータを実装し、それがvector::iteratorから構築可能であることが必要ですし、要件を満たすために必要なすべての演算子をオーバーロードあなたの新しいイテレーターがモデル化するという概念のまた、特性を得るためにstd::iteratorから継承します。 const型を持つことを忘れないでください。 This bookには、独自のイテレータを開発するための章があります。また、標準のコピーを入手してください(C++ 03またはC++ 11、これはあまり重要ではありません)。あなたはそれを必要とするでしょう。

+1

もし彼がそれを透過的に使用したいのであれば(彼の質問が示唆しているように)彼は 'std :: vector'のためのラッパーを実装する必要があります。 –

+0

@BjörnPollexクラスは、アダプターが必要なように見えます。彼のクラスは 'Sequence'の完全なモデルとして意図されておらず、' begin() 'と' end() 'が公開されるのはイテレータだけです。 – pmr

1

残念ながら、これを実行する唯一の方法は、std::vectorとそのイテレータタイプの完全なラッパーを記述することです。これはたくさんの仕事です。

-1

ここでの答えは、おそらくではありません。イテレータの演算子*の動作を変更しないでください。演算子のオーバーロードは、演算子を使用するコードを読んでいる人が何が起こっているのかを自動的に知るように、非常に直観的な場合にのみ行う必要があります。この例は、行列クラスとオーバーロードされた演算子+がある場合です。誰かがあなたに2つのマトリックスオブジェクトを追加するのを見ると、何が起きているのかを簡単に知ることができます。

ただし、イテレータの参照を解除すると、追加の副作用がクラスにどのようなものになるか直感的に分かりません。

+1

ああ、 'operator *'の振る舞いを変えることは非常に便利です。 「変換イテレータ」を考える。 – pmr

1

クラスである必要はないため、std::vector<T>::iteratorから継承しません。いくつかの実装では、これはちょうどT*のtypedefであり、ポインタから継承することはできません。仮想デストラクタがないため、標準コンテナから継承してはいけません。可能性としてprivateまたはprotectedの方法で継承し、すべてのシンボルと機能をtypedefusingで表示することができます。結局、呼び出しを基本実装に転送するベクトルとそのイテレータ全体を書き直す必要があります。

関連する問題