4

私は大学で OOP コース (C++ がベース言語) を勉強しています。私の仕事は、独自のリンク リスト テンプレート コンテナー クラスを実装することです。私はそれをほぼ完全にやりましたが、問題に直面しました。STL は、リストを反復処理するためのiteratorおよびクラスを提供することが知られています。const_iteratorそれらの実装はほぼ同じです。主な違いは、反復子のメソッドが参照を返すのに対し、const_iterator のメソッドは定数参照を返すことです。https://stackoverflow.com/a/3582733/2108548に従い、別のテンプレート クラスを作成しましたListIterator。次に、クラスで宣言し、typedefクラス内で宣言しました。IteratorConstIteratorList

私はこのようなものを得ました:

template<typename T>
class ListNode
{
public:
    ListNode(T *node_value = nullptr, ListNode *node_prev = nullptr, ListNode *node_next = nullptr):
        value(node_value), prev(node_prev), next(node_next) { }

    T *value;
    ListNode *prev, *next;
};

template<typename T>
class ListIterator
{
    typedef ListNode<T> Node;

public:
    ListIterator();
    ListIterator(Node *node);
    ListIterator(ListIterator const &other);
    ListIterator &operator++();
// ...
    Node *i;
};

template<typename T>
class List: public Container
{
    typedef ListIterator<T> Iterator;
    typedef ListIterator<T const> ConstIterator;
// ...
    Iterator begin() const
    {
        return Iterator(m_first->next);
    }
    ConstIterator const_begin() const
    {
        return ConstIterator(begin());
    }
// ...
};

「コピーコンストラクター」を作成することを決定するまで、すべてうまくいきましたIterator-> ConstIterator. したがって、 ListIterator<T>(データ クラス名はどこにTあるのか) を取得し、新しいオブジェクト タイプを作成するコンストラクタ メソッドが必要ListIterator<T const>です。しかし、実際にConstIteratorは のコンストラクターはT constテンプレート パラメーターとして取得されるためconst、コンストラクターのパラメーターを削除する必要があります。これを行うヘッダーが見つかりましtype_traitsた。だから私は「コピーコンストラクタ」を書きました: typedef typename std::remove_cv::type NoConstT; ListIterator(ListIterator const &other);

しかし、うまくいきません!const_begin() をリクエストした後、次のエラーが発生しました。

List<int> list1;
list1 << 1 << 2 << 3;
int i = *list1.const_begin(); 

error: 'ListIterator<T>::ListIterator(const ListIterator<typename std::remove_cv<_Tp>::type>&) [with T = int; typename std::remove_cv<_Tp>::type = int]' cannot be overloaded with 'ListIterator<T>::ListIterator(const ListIterator<T>&) [with T = int; ListIterator<T> = ListIterator<int>]'

しかし、それだけではありません。私の目標を達成するには、同様に変換ListNode<T>する必要があります。ListNode<T const>しかし、もう 1 つ問題があります。各リスト ノードには、前のノードと次のノードへのポインターが含まれており、ノードのコンストラクターでそれらを初期化しようとすると、再帰が発生します。もちろん、すべてのListNode<T>ノードをListNode<T const>反復して変換する関数を作成できます。しかし、私はこの解決策が好きではありません。オーバーヘッドが非常に大きくなります!

私は先生にこの質問をしました。彼は数分間それを理解することができませんでした。— 「でも、私は 3 ~ 4 時間続けました!」— 「もしそうなら、const イテレータを捨てて、それらなしでリスト コンテナをファイナライズしてください。あなたのコードを理解するには時間が必要です」(私の意見では、私のコードは非常に単純です)。私が理解したように、彼はこの質問に対する答えを知りませんでした。でも、作り方が知りたい!どうすればこの問題を解決できますか?

たくさんの間違いをお詫びします — 私は英語のネイティブ スピーカーではありません。

4

1 に答える 1