Renaming first and second of a map iterator

匿名 (未验证) 提交于 2019-12-03 02:05:01

问题:

Is there any way to rename the first and second accessor functions of a map iterator. I understand they have these names because of the underlying pair which represents the key and value, but I'd like the iterators to be a little more readable. I think this might be possible using an iterator adaptor, but I'm not sure how to implement it.

Please note that I can't use boost.

Example of what I mean:

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

回答1:

If you're just concerned about readability you could do something like this:

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

And then:

Vertex v = adjacency(it).vertex; 


回答2:

You can't rename the members, but you can have some functions to help.

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

Then, instead of it->vertex like you want, you can do vertex(it)



回答3:

Unfortunately, no. What I usually do is this:

typedef map AdjacencyList; typedef AdjacencyList::value_type Vertex_Edge_Pair; 

For readability. Inside your loop you can also say

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


回答4:

Sure, reimplement or wrap iterator, but is it worth the effort? Wouldn't

Vertex& v = it->first; 

be easier?



回答5:

I wouldn't recommend really using this, but it does seem to work, at least to the minimum degree of the test program doing what I wanted/expected:

#include  #include  #include   template  struct my_pair : public std::pair {     T const &vertex;     my_pair(std::pair const &x) : std::pair(x), vertex(x.first) { } };  template  struct my_map : public std::map {      my_pair find(T const &t) { return my_pair(*std::map::find(t)); } };  class Vertex {      int x; public:     Vertex(int v) : x(v) {}     bool operator m;      m[1] = "This is it";      my_pair mp = m.find(1);     std::cout 


回答6:

I liked KeithB's solution with free functions. However, a more reusable solution might be nice.

What about function objects that access first or second, as you can name the instances anything you like:

#include  #include  #include   struct GetFirst {     template      First& operator()(std::pair& p)     {         return p.first;     }      template      const First& operator()(const std::pair& p)     {         return p.first;     } };  struct GetSecond {     template      Second& operator()(std::pair& p)     {         return p.second;     }      template      const Second& operator()(const std::pair& p)     {         return p.second;     } };  int main() {     typedef std::map<: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 

This is the best I could do. I also tried to make those functors accept the iterator directly, but one way or another this means that the signature will contain dependent names which apparently makes template type deduction impossible (I couldn't find a way to overload GetSecond for iterator/const_iterator even with deferred return type of C++0x).



回答7:

I've got an evil solution!

#define vertex first #define edge second 

Although as an evil solution it will doubtless cause great trauma and difficult to diagnose compilation problems when you accidentally use those words elsewhere.

Added for completeness.

Can't believe nobody else has suggested this.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!