2009-09-30 17 views
16

का पहला और दूसरा नाम बदलना मानचित्र इटरेटर के पहले और दूसरे एक्सेसर फ़ंक्शंस का नाम बदलने का कोई तरीका है। मैं समझता हूं कि इन नामों में अंतर्निहित जोड़ी है जो कुंजी और मूल्य का प्रतिनिधित्व करती है, लेकिन मैं चाहता हूं कि इटरेटर थोड़ा और पठनीय हो। मुझे लगता है कि यह एक इटरेटर एडाप्टर का उपयोग कर संभव हो सकता है, लेकिन मुझे यकीन नहीं है कि इसे कैसे कार्यान्वित किया जाए।नक्शा इटेटर

कृपया ध्यान दें कि मैं बूस्ट का उपयोग नहीं कर सकता।

मैं क्या मतलब का उदाहरण:

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

क्या आप कुछ इस तरह कर सकता है पठनीयता के बारे में सिर्फ चिंतित हैं, तो:

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

और फिर:

Vertex v = adjacency(it).vertex; 
5

ज़रूर, reimplement या इटरेटर लपेट, लेकिन यह प्रयास के लायक है?

Vertex& v = it->first; 

आसान होना चाहिए?

+3

यह भी याद रखें कि std :: मैप इटेटरेटर का पहला और दूसरा उपयोग करना एक आम मुहावरे है कि आप किसी को भी अपना कोड पढ़ने में भ्रमित करेंगे - थोड़ा। – phoku

+3

यह सच है, लेकिन सैनिटी परिप्रेक्ष्य से, 'पहला' और 'दूसरा' पर्याप्त भ्रमित कर रहे हैं ;-) –

7

दुर्भाग्य से, नहीं। मैं आमतौर पर यह करता हूं:

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

पठनीयता के लिए। अपने पाश अंदर आप यह भी कह सकते

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

आप नहीं कर सकते हैं सदस्यों का नाम बदलें, लेकिन आपके पास मदद करने के लिए कुछ कार्य हो सकते हैं।

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)

+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

मुझे मुफ्त कार्यों के साथ कीथबी का समाधान पसंद आया। हालांकि, एक और पुन: प्रयोज्य समाधान अच्छा हो सकता है।

क्या समारोह वस्तुओं है कि पहली या दूसरी का उपयोग, जैसा कि आप नाम कर सकते हैं उदाहरणों कुछ भी आप की तरह के बारे में:

#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'; 
    } 
} 

यह सबसे अच्छा मैं कर सकता है। मैंने उन मज़ेदारों को सीधे इटरेटर को स्वीकार करने की कोशिश की, लेकिन एक तरफ या दूसरा इसका मतलब है कि हस्ताक्षर में निर्भर नाम होंगे जो स्पष्ट रूप से टेम्पलेट प्रकार की कटौती को असंभव बनाता है (मुझे iterator/const_iterator के लिए गेटसेकंड को अधिभारित करने का कोई तरीका नहीं मिला, यहां तक ​​कि स्थगित वापसी के साथ भी सी ++ 0x का प्रकार)।

0

मुझे एक बुरा समाधान मिला है!

#define vertex first 
#define edge second 

हालांकि एक बुराई समाधान के रूप में यह निस्संदेह संकलन समस्याओं का निदान करने अगर आप गलती से कहीं और उन शब्दों का उपयोग करते हैं महान आघात और मुश्किल का कारण होगा।

पूर्णता के लिए जोड़ा गया।

विश्वास नहीं कर सकता कि किसी और ने इसका सुझाव नहीं दिया है।

+0

किसी और ने इसका सुझाव नहीं दिया क्योंकि यह एक भयानक विचार है। – user1353535

संबंधित मुद्दे