2017-06-16 1 views
-2

簡単にするためにキーがintのマップがあり、最小限のコンパイル例で問題を再現できるとします。私の場合、鍵ははるかに複雑な獣です。イテレーターは自分の立場に精通していますか?

intの代わりにenumと言う別のマップを作成するために、このマップを再利用したいと思います。このために私はintenumに変換することを可能にする2つの機能を持っており、その逆もあります。

全体ではなくクラスを書き換え、私は、組成物を使用して、私は私の新しいクラスMYMAP内部この場合には(map<int,int>を自分のマップを置く。

私は次の実装を始めたが、私はカスタムに問題があります

class myMap 
{ 
private: 
    std::map<int, int> m; 

public: 

    typedef std::map<int, int> map_type; 
    typedef enum { X1=0, X2, X3, INVALID } key_type; 
    typedef int mapped_type; 
    typedef pair<key_type, mapped_type> value_type; 

    /* conversions from int to key_type and vice versa */ 
    friend key_type int2K(int k); 
    friend int K2int(key_type k); 

    class Iterator 
    { 
    private: 
     map_type::iterator it; 
     key_type K; 
    public: 

     Iterator(map_type::iterator & i) : 
       it(i), K(int2K(i->first)) {} //<= Error if i is not valid (points to the end) 
    }; 

    typedef Iterator iterator; 

    iterator end() { return iterator(m.end()); } 
    // other parts of the class skipped for concisness 
}; 

myMap::key_type int2K(int k) { 
    return (k == 0 ? myMap::X1 : 
      (k == 1 ? myMap::X2 : 
      (k == 3 ? myMap::X3 : 
        myMap::INVALID))); } 

int K2int(myMap::key_type k) { return k; } 

私はマップの最後にMYMAPのイテレータを初期化すると、それは失敗します:

私は std::iteratorを継承することを選択し、また map<int,int>::iteratorからではなく、再構成を使用していない私のクラスAのイテレータ
myMap m; 
myMap::iterator i = m.end(); //<= fails here 

イテレータがマップの最後を指しているかどうかをコンストラクタでチェックする方法はありますか?もしそうなら、どのように?

+1

「Iterator」を参照するときにのみ変換を行うことができます。 – Jarod42

+2

ブーストでiterator_facadeをチェックアウト – sp2danny

+0

@ sp2danny iterator_facadeは知っていますが、私の問題を解決するつもりはありません。私の問題は、イテレータがどのインタフェースを満たす必要があるかを知ることではなく、イテレータクラスの設計上の問題です。 – Heyji

答えて

1

短い答えはノーです。質問のコメントでzett42が述べたように、反復子の位置が分かっている唯一の場所は反復子呼び出し側です。

Iterator(map_type::iterator & i): it(i) {}; 

value_type operator*() { 
    return { int2K(it->first), it->second}; 
} 

注:元の答えで、私がしようとしたJarod42が示唆するように、解決策は、同等のキーイテレータを逆参照のみKを計算することによって見つけることができる、しかし問題を解決するために

イテレータがコンテナの最後にあるかどうかテストします。イテレータをコピーし、コピーを1つインクリメントし、コピーが元のポインタ(終点を指している)と同じかどうかを確認します。

しかしzett42が指摘したように、これは動作しません: - コンテナの末尾を指すイテレータをインクリメントすると、未定義の振る舞い する必要があります - でも、シンプルなポインタはイテレータとしての資格。この場合、この解決策が機能しないことは自明です。

/* DISCLAIMER: Not working ! */ 
Iterator(map_type::iterator & i) : it(i), K(INVALID) 
{ 
    map_type::iterator j = i; 
    j++; 
    if(i!=j) K = int2K(i->first); 
} 
+0

[動作しません](http://coliru.stacked-crooked.com/a/27b9c61bec8ecd55)。そして、これがうまくいくとはどのように思いますか?イテレータはコンテナに関する情報を保持する必要はありません。通常のポインタでもイテレータとしての資格があります。 – zett42

+0

@ zett42:ありがとうございます。私は答えを更新しました。あなたのコメントも更新したいと思うかもしれません(そしてあなたの投票:-) – Heyji

関連する問題