2

良い設計であるかどうかにかかわらず、私のメソッドは、使用されているデータ構造(入力引数によって決定される)に基づいて、定義(特にまたは)をmain()満たすイテレーターを期待する必要がある変数を宣言します。メソッドをテンプレート化できないので、これをどのように達成しますか?BidirectionalIteratorlist<>::iteratorvector::iteratormain()

たとえば、次の代わりに:

int main(int argc, const char* argv[]) {
    vector<Person>::iterator iterator0;
    list<Person>::iterator iterator1);
    multimap<string, Person>::iterator iterator2;
}

そこにあるすべてのイテレータはの要件を満たしているのでBidirectionalIterator、次のことを実行します。

int main(int argc, const char* argv[]) {
    bidirectionaliterator iterator0;
}

次に、プログラムがifステートメントで使用しているデータ構造の種類を継続的にチェックして、イテレーターを格納し、必要なイテレーターを使用する必要はありません。

4

2 に答える 2

1

あなたが探しているのはType Erasureだと思います。インターフェイスの逆と考えることができます。インターフェイスはクラスの最下部に位置し、提供する必要があるメソッドを決定するものと考えることができます。タイプが消去されたオブジェクトが上部にアタッチされ、特定のメソッドが「抽出」され、ダックタイピングが行われます。これを使いやすいコンセプトにする今後の Boost Type Erasure ライブラリがあります。

プレーンなC++ 11での動作は次のとおりです(11より前のC ++でも簡単に動作させることができますが、使用したかったのですunique_ptr):

#include<iostream>
#include<vector>
#include<list>
#include<memory>
using namespace std;

class Person{};


template <class T>
class TypeErasedBidirectionalIterator {
public:
    virtual void operator++()=0;
    virtual void operator--()=0;
    virtual T& operator*()=0;
};

template <class T, class Iterator> 
class BidirectionalIteratorAdaptor: public TypeErasedBidirectionalIterator<T> {
    Iterator it;
public:
    BidirectionalIteratorAdaptor(Iterator it): it(it){}
    void operator++(){it++;}
    void operator--(){it--;}
    T& operator*(){*it;}
};

template <class Iterator>
unique_ptr<BidirectionalIteratorAdaptor<typename Iterator::value_type,Iterator> > makeIterator(Iterator it) {
    typedef typename Iterator::value_type T;
    return unique_ptr<BidirectionalIteratorAdaptor<T,Iterator> >(new BidirectionalIteratorAdaptor<T,Iterator>(it));
}

typedef TypeErasedBidirectionalIterator<Person> PersonIterator;
typedef unique_ptr<PersonIterator> PersonIteratorPtr;


int main() {
    vector<Person> vec;
    list<Person> lst;
    lst.push_back(Person());
    PersonIteratorPtr it = makeIterator(vec.begin());
    it = makeIterator(lst.begin());
    ++*it;
    --*it;
    **it;
}

メソッドを直接公開する別のクラス内にラップするPersonIteratorPtrことで、ポインターのような動作を取り除くことができますが、概念実証をこれ以上複雑にしたくなかったことに注意してください。

于 2013-02-18T05:40:44.060 に答える
1

typedefが必要なようです:

typedef std::vector<Person> person_container;
typedef person_container::iterator mybidirectionaliterator;

その後、基礎となるコンテナーを変更したいときはいつでも、別のstd::vector<Person>ものに変更するだけで済みます。ここでも反復子を割り当てることはできませんが、互換性のある反復子を使用する必要があります。autoしかし、 C++11のキーワードに精通していますか? 多くの場合、イテレータを書き出す必要はありません。つまり、これauto myiter = some_container.begin();で十分です。

また、イテレータを宣言するだけでなく、イテレータをどのように使用しているかを示すと、より良い答えが得られます。

于 2013-02-18T05:12:31.373 に答える