1

リンクされたリストに基づいてコンテナー Set を実装しようとしているときに、少し問題が発生しました。ええ、セットの STL 実装があることは知っていますが、これは宿題です。:)

だから、これは私がこれまでに行ったことです:

私の Set.h ファイルは次のようになります。

template <class T>
class Set {
private:
    typedef std::list<T> base_container;
    base_container items;
public:
    class myIterator {
    public:
        typename base_container::iterator base_iterator;
        myIterator() { }
    };
    void addItem(const T item) {
        items.push_back(item);
    }
    typedef typename Set<T>::myIterator setIterator;
    setIterator begin() { return items.begin(); }
    setIterator end() { return items.end(); }
    Set<T>(void) { }
    ~Set<T>(void) { }
};

さて、main.cpp:

#include "Set.h"

int main(void) {
    Set<int> mySet;

    mySet.addItem(1);
    mySet.addItem(2);
    mySet.addItem(3);
    mySet.addItem(4);

    Set<int>::myIterator x;
    x = mySet.begin();       // produces an error about non-convertible types.

    return EXIT_SUCCESS;
}

エラーは次のとおりです。

error C2664: 'Set<T>::myIterator::myIterator(const Set<T>::myIterator &)' : cannot convert parameter 1 from 'std::_List_iterator<_Mylist>' to 'const Set<T>::myIterator &' 

明らかに私は物事を台無しにしましたが、コードのどの部分が実際に問題なのかはわかりません。これを修正する方法について何か提案はありますか? 役立つ情報をいただければ幸いです。

ありがとう。:)

4

3 に答える 3

2

あなたのアプローチには多くの問題があります。

他の人が言ったように、基になる型からイテレータ型を作成することはできません:

setIterator begin() { return items.begin(); }
setIterator end() { return items.end(); }

これは、型にコンストラクターを追加することで解決できます。

class myIterator {
    typedef typename base_container::iterator base_iterator_type;
public:
    explicit myIterator(base_iterator_type i) : base_iterator(i) { }
    base_iterator_type base_iterator;
    myIterator() { }
};

このコンストラクターは明示的である必要があります。つまり、作成方法を変更する必要があります。

setIterator begin() { return setIterator(items.begin()); }

次の問題は、型がイテレータ インターフェイスを実装していない、提供していない、operator++などoperator*であり、ネストされた型を定義していないvalue_typeiteratory_categoryつまり、イテレータではありません (「イテレータ」で名前を付けるだけです)。それは真実にはなりません!)

それを修正し、型が有効な反復子になると、コンテナーの要件を実装していないため、コンテナーを STL スタイルのアルゴリズムで使用できないことがわかります。とりわけ、他のテンプレート コードが aか a かを気にせずに使用できるように、 iteratornotと呼ばれるネストされた型を提供する必要があります。呼び出さないで、ただ呼び出してください。また、この場合、定義する意味はありません(誰もそれがあなたのものであることを気にしません! :-) 次に、それを呼び出すための typedef を持ちます。最初に正しい名前で型に名前を付けるだけで、typedef は必要ありません。setIteratorS::iteratorSstd::set<T>Set<T>Set<T>::setIteratorSet<T>::iteratormyIteratorsetIterator

于 2013-01-19T14:41:41.277 に答える
1

std::iterator<T>適切なイテレータカテゴリタグから派生して提供できます。value_typeこれにより、イテレータに、などの必要なネストされた型が自動的に与えられますToperator++およびなどの関数メンバーを作成する必要がありoperator*ます(イテレータのカテゴリによって異なります。たとえばoperator[]、ランダムアクセスイテレータも必要です) 。

于 2013-01-19T14:15:08.783 に答える
1

問題はここにあります:

setIterator begin() { return items.begin(); }
setIterator end() { return items.end(); }

返そうとしている値のタイプが間違っています。それらはタイプbase_iteratorであり、ではなくsetIterator、前者から後者に暗黙的に変換する方法はありません。

于 2013-01-19T14:16:08.890 に答える