2009-09-30 24 views
16

マップイテレータの1番目と2番目のアクセサ関数の名前を変更する方法はありますか。キーと値を表す基本的なペアのためにこれらの名前があることは理解していますが、イテレーターを少し読みやすくしたいと思います。私はこれがイテレーターアダプターを使用して可能かもしれないと思うが、私はそれを実装する方法がわからない。マップイテレータの1番目と2番目の名前の変更

私はブーストを使用できませんのでご注意ください。

私が何を意味するかの例:

map<Vertex, Edge> adjacency_list; 
for(map<Vertex, Edge>::iterator it = adjacency_list.begin(); 
    it != adjacency_list.end(); 
    ++it) 
{ 
    Vertex v = it->first; 
    //instead I would like to have it->vertex 
} 
+1

面白い:現在、グラフに関する多くの質問があるようです:http://stackoverflow.com/questions/1499878/use-a-graph-library-node-network-library-or-roll-my-自分自身、http://stackoverflow.com/questions/1499217/boost-graph-as-basis-for-a-simple-dag-graph –

+0

なぜブーストを使用できないのですか? –

答えて

15

を言うことができますメンバーの名前を変更しますが、いくつかの機能を持たせることができます。あなたが望むように続いて

inline Vertex& vertex(map<Vertex, Edge>::iterator& it) {return it->first;} 
inline Edge& edge(map<Vertex, Edge>::iterator& it) {return it->second;} 

、代わりの it->vertex、あなたが行うことができます vertex(it)

5

確かに、イテレータを再実装やラップ、それは努力の価値がありますか?そうでないでしょう

Vertex& v = it->first; 

もっと簡単ですか?

+3

また、std :: mapイテレータの1番目と2番目を使用することは、あなたのコードを読んでいる人を混乱させるような共通のイディオムであることを覚えておいてください。 – phoku

+3

真実だが、健全性の観点から、 'first'と' second'は十分混乱している;-) –

7

残念ながら、私が普段やっていることは次のとおりです。

typedef map<Vertex, Edge> AdjacencyList; 
typedef AdjacencyList::value_type Vertex_Edge_Pair; 

読みやすくするためです。あなたがすることはできません

Vertex v = adjacency(it).vertex; 
12

:その後、

typedef map<Vertex, Edge> AdjacencyList; 
struct adjacency 
{ 
    adjacency(AdjacencyList::iterator& it) 
     : vertex(it->first), edge(it->second) {} 
    Vertex& vertex; 
    Edge& edge; 
}; 

そして:あなたはこのような何かを行うことができ、読みやすさについてだけ心配している場合は、あなたのループ内には、また

Vertex& current_vertex = it->first; 
Edge& current_edge = it->second; 
+1

+1 const_iteratorsのオーバーロードも追加する。 – UncleBens

1

私はこれを使用して、本当にお勧めしませんが、少なくともテストプログラムの最小程度に、動作するようには思えません

#include <map> 
#include <string> 
#include <iostream> 

template <class T, class U> 
struct my_pair : public std::pair<T, U> { 
    T const &vertex; 
    my_pair(std::pair<T, U> const &x) : std::pair<T, U>(x), vertex(x.first) { } 
}; 

template <class T, class U> 
struct my_map : public std::map<T, U> { 
    my_pair<T, U> find(T const &t) { return my_pair<T, U>(*std::map<T,U>::find(t)); } 
}; 

class Vertex { 
    int x; 
public: 
    Vertex(int v) : x(v) {} 
    bool operator<(Vertex const &other) const { return x < other.x; } 
    friend std::ostream &operator<<(std::ostream &os, Vertex const &v) { return os << v.x; } 
}; 

int main() { 
    my_map<Vertex, std::string> m; 

    m[1] = "This is it"; 

    my_pair<Vertex, std::string> mp = m.find(1); 
    std::cout << mp.vertex << ": " << mp.second; 
    return 0; 
} 
1

無料の機能を備えたKeithBのソリューションが好きだった。しかし、より再利用可能なソリューションが良いかもしれません。

あなたはインスタンスの任意の名前を付けることができますよう、あなたが好きな、第一または第二のアクセス関数オブジェクトについて:

#include <map> 
#include <string> 
#include <iostream> 

struct GetFirst 
{ 
    template <class First, class Second> 
    First& operator()(std::pair<First, Second>& p) 
    { 
     return p.first; 
    } 

    template <class First, class Second> 
    const First& operator()(const std::pair<First, Second>& p) 
    { 
     return p.first; 
    } 
}; 

struct GetSecond 
{ 
    template <class First, class Second> 
    Second& operator()(std::pair<First, Second>& p) 
    { 
     return p.second; 
    } 

    template <class First, class Second> 
    const Second& operator()(const std::pair<First, Second>& p) 
    { 
     return p.second; 
    } 
}; 

int main() 
{ 
    typedef std::map<std::string, int> Map; 

    Map persons; 
    persons["John"] = 20; 
    persons["Mary"] = 24; 

    //create named accessors 
    GetFirst name; 
    GetSecond age; 

    for (Map::iterator it = persons.begin(); it != persons.end(); ++it) { 
     std::cout << name(*it) << " is aging.\n"; 
     ++age(*it); 
    } 

    for (Map::const_iterator it = persons.begin(); it != persons.end(); ++it) { 
     std::cout << "Name: " << name(*it) << ", age: " << age(*it) << '\n'; 
    } 
} 

これは私が何ができる最善の方法です。私はまた、それらのファンクターがイテレータを直接受け入れるようにしようとしましたが、これは、シグネチャに依存型の名前が含まれている可能性があることを意味します(つまり、Get34 C++ 0xのタイプ)。

0

私は邪悪な解決策を持っています!邪悪なソリューションとして、それは間違いなくあなたが誤って別の場所でそれらの単語を使用するときにコンパイルの問題を診断するために偉大なトラウマや困難を引き起こしますが

#define vertex first 
#define edge second 

完全性のために追加されました。

他に誰もこれを示唆しているとは考えられません。

+0

それはひどい考えであるので、他に誰もこれを示唆していません。 – user1353535

関連する問題