2010-02-06 17 views
14
struct Node 
{ 
int a; 
int b; 
}; 

Node node; 
node.a = 2; 
node.b = 3; 

map<int, int> aa; 
aa[1]=1; //O.K. 

map<Node, int> bb; 
bb[node]=1; //Compile Error 

जब मैंने int में संरचना को मैप करने का प्रयास किया, तो उसने मुझे संकलन त्रुटि दी। क्यों? धन्यवाद!संरचना के साथ stl मानचित्र का उपयोग करना असंभव है?

उत्तर

23

किसी मानचित्र में किसी कुंजी के रूप में प्रयोग करने योग्य होने के लिए, आपको operator<() का उपयोग करके इसकी तुलना करने में सक्षम होना चाहिए। आपको अपने नोड क्लास में ऐसे ऑपरेटर को जोड़ने की आवश्यकता है:

struct Node 
{ 
int a; 
int b; 

bool operator<(const Node & n) const { 
    return this->a < n.a; // for example 
} 
}; 

बेशक, वास्तविक ऑपरेटर क्या करता है इस बात पर निर्भर करता है कि वास्तव में आपकी संरचना के लिए वास्तव में क्या मतलब है।

+0

के लिए वोटिंग सभी को धन्यवाद! मुझे नहीं लगता था कि मानचित्र की तुलना की आवश्यकता है। – sevity

+1

@Steve और भी सटीक होने के लिए, पॉइंटर्स तुलनात्मक नहीं हो सकते हैं <- यह निर्भर करता है कि वे क्या इंगित करते हैं। –

+0

हां, मेरा मतलब क्या था, "उसी प्रकार के पॉइंटर्स सामान्य रूप से' <'" के साथ तुलनीय नहीं हैं। उसी ऑब्जेक्ट/सरणी के विभिन्न हिस्सों के पॉइंटर्स तुलनीय हैं, और उस मामले के लिए यदि कार्यान्वयन ऐसा कहता है तो सभी पॉइंटर्स तुलनीय हो सकते हैं। –

1

आप संकलक त्रुटि पोस्ट कृपया सकते हैं - वे आप, क्या गलत है बताने के लिए इरादा कर रहे हैं।

मुझे लगता है कि आपकी त्रुटि तब होती है जब Node एक तुलना ऑपरेटर को लागू नहीं करता है जो इसके तत्वों की पहचान करने के लिए मानचित्र द्वारा आवश्यक है।

9

आपको std :: मानचित्र को नोड ऑब्जेक्ट्स की तुलना करने के तरीके को बताना होगा। डिफ़ॉल्ट रूप से यह ऑपरेटर से कम का उपयोग करके ऐसा करने का प्रयास करता है। लेकिन आपने नोड के लिए ऑपरेटर से कम प्रदान नहीं किया था। सबसे आसान समाधान एक आपूर्ति करना होगा।

नि: शुल्क समारोह उदाहरण:

bool operator<(Node const& n1, Node const& n2) 
{ 
    return n1.a<n2.a || (n1.a==n2.a && n1.b<n2.b); 
} 

ध्यान दें कि, !(x<y) और !(y<x) साथ की नोड वस्तुओं एक्स किसी भी जोड़ी, y के लिए नक्शा बराबर (एक ही कुंजी) के रूप में x और y में मानेंगे।

+0

समानता टिप्पणी – VillasV

6

आप अपने नोड प्रकार के लिए तुलना सक्षम करने के लिए कम-से ऑपरेटर निर्धारित करने होंगे:

struct Node 
{ 
int a; 
int b; 
}; 

bool operator<(Node const& n1, Node const& n2) 
{ 
    // TODO: Specify condition as you need 
    return ... ; 
} 

यहाँ आप जाँच कर सकते हैं जो एक उपयोगकर्ता-निर्धारित प्रकार के लिए मतलब LessThan Comparable

वैकल्पिक समाधान std::binary_function पर आधारित एक मजेदार को परिभाषित करना है। डिज़ाइन बिंदु दृश्य से, इस विकल्प के फायदे हैं क्योंकि तुलना Node कक्षा से प्रभावी ढंग से decoupled है। इससे विभिन्न तुलना स्थितियों (मज़ेदार) के साथ विशेष मानचित्रों को परिभाषित करना संभव हो जाता है।

#include <map> 

struct Node 
{ 
int a; 
int b; 
}; 

struct NodeLessThan 
    : public std::binary_function<Node, Node, bool> 
{ 
    bool operator() (Node const& n1, Node const& n2) const 
    { 
     // TODO: your condition 
     return n1.a < n2.a; 
    } 
}; 

int main() 
{ 
    Node node; 
    node.a = 2; 
    node.b = 3; 

    typedef std::map<Node, int, NodeLessThan> node_map_t; 
    node_map_t bb; 
    bb[node] = 1; 
} 

तो, आप अलग अलग परिस्थितियों या Node::a एक और दोनों घटकों, Node::a और Node::b तुलना करके केवल एक का उपयोग कर की तुलना सिर्फ NodeLessThan की तुलना में अधिक तुलना, उदाहरण के लिए परिभाषित कर सकते हैं। फिर, नक्शे के विभिन्न प्रकार परिभाषित:

typedef std::map<Node, int, NodeLessThan> node_map_t; 
typedef std::map<Node, int, NodeLessThanByA> node_map_a_t; 

इस तरह के decoupling कम दखल है (बिल्कुल नोड वर्ग स्पर्श नहीं करता है) और अधिक विस्तृत समाधान प्राप्त करने के लिए फायदेमंद है।

3

तुम सच में अपने डेटा कुंजी के अनुसार क्रमबद्ध है की जरूरत नहीं है, तो आप नए unordered_map उपयोग कर सकते हैं:

#include <unordered_map> 

... 

std::tr1::unordered_map<Node, int> aa; // Doesn't require operator<(Node, Node) 

आप इस काम करने के लिए हाल ही में एक संकलक की आवश्यकता होगी।

अद्यतन नील के रूप में बताते हैं तो आप एक विशेष हैश समारोह की जरूरत है अगर आप Node कुंजी के साथ एक unordered_map चाहते हैं।

struct NodeHash : std::unary_function<Node, size_t> 
{ 
    size_t operator()(Node const & node) const 
    { 
     return static_cast<size_t>(node.a + 1) * static_cast<size_t>(node.b + 1); 
    } 
}; 

और फिर नक्शा हो जाता है:

std::tr1::unordered_map<Node, int, NodeHash> aa; 

इसके अलावा, जैसा sellibitze कहते हैं, एक ऑपरेटर == हैश टकराव के मामले में चाबियाँ की तुलना करने की जरूरत है:

bool operator==(const Node & lhs, const Node & rhs) 
{ 
    return lhs.a == rhs.a && rhs.b == rhs.b; 
} 

तो मैं अनुमान लगाएं कि std :: नक्शा सभी के बाद उपयोग करना बहुत आसान है।

+4

आप सही हैं - आपको ऑपरेटर की आवश्यकता नहीं है <()। लेकिन इसके बजाय आपको एक हैश फ़ंक्शन प्रदान करना होगा, जो आमतौर पर ऑपरेटर <() से लिखना कठिन होता है। –

+0

@Neil: धन्यवाद, मैंने अपना जवाब अनुकूलित करने का प्रयास किया है। – Manuel

+0

@ मैनुअल मुझे लगता है कि आपने अच्छी तरह से दिखाया है कि एक अच्छा हैश फ़ंक्शन लिखना कितना मुश्किल है :-) आपके फ़ंक्शन के पास (ए, बी) जोड़े (0,1) और (1) के लिए एक ही मान (1) होगा 0) और कई अन्य जोड़े के लिए भी। –

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