2012-02-03 5 views
8

मुझे अपने आवेदन में सेट का एक सेट लागू करने की आवश्यकता है। कस्टम क्लास के साथ क्यूसेट का उपयोग करने के लिए qHash() फ़ंक्शन और operator== प्रदान करना आवश्यक है।एक QSet <SomeClass*> कंटेनर के लिए qHash कैसे लिखें?

class Custom{ 
     int x; 
     int y; 
     //some other irrelevant here 
    } 
    inline uint qHash(Custom* c){ 
     return (qHash(c->x)^qHash(c->y)); 
    } 
    bool operator==(Custom &c1, Custom &c2){ 
     return ((c1.x==c2.x) && (c1.y == c2.y)); 
    } 

    //now I can use: QSet<Custom*> 

मैं qHash(QSet<Custom*>) कैसे लागू कर सकते हैं, QSet< QSet<SomeClass*> > उपयोग करने के लिए सक्षम होने के लिए:

कोड इस प्रकार है?

संपादित करें:

अतिरिक्त प्रश्न: अपने आवेदन में "सेट के सेट" अप करने के लिए 15000 सेट हो सकते हैं। 25 कस्टम क्लास पॉइंटर्स तक प्रत्येक सबसेट। कैसे गारंटी है कि qHash(QSet<Custom*>) पर्याप्त अद्वितीय होगा?

+0

आप 'QSet ' बारे में सुनिश्चित हैं: सौभाग्य से, दोनों (अहस्ताक्षरित) इसके अलावा और XOR आपरेशन सिर्फ बिल फिट? क्या यह 'QSet ' नहीं होना चाहिए? 'कस्टम' के लिए आपका 'ऑपरेटर ==' कभी भी 'क्यूहाश' द्वारा नहीं बुलाया जाएगा, क्योंकि यह पॉइंटर्स के लिए अंतर्निहित समानता ऑपरेटर का उपयोग करता है। –

उत्तर

4

एक आम तरीका कंटेनर हैश करने के लिए सभी तत्वों के हैश गठबंधन करने के लिए है। बूस्ट इस उद्देश्य के लिए hash_combine and hash_range प्रदान करता है। यह आपको अपने qHash के परिणामों के लिए इसे कार्यान्वित करने का विचार देना चाहिए।

uint qHash(const QSet<Custom*>& c) { 
    uint seed = 0; 

    for(auto x : c) { 
    seed ^= qHash(x) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 
    } 

    return seed; 
} 
+0

यह मेरा पहला विचार था, लेकिन क्या मुझे यकीन है कि हैश अद्वितीय होगा? बेशक मैं इसे अपने कोड में देख सकता हूं, लेकिन शायद उसके पीछे कुछ सिद्धांत है? – Piotr

+0

@piotr आप इसे अपने प्रश्न में जोड़ना चाहते हैं। अब आप केवल एक कार्यान्वयन के लिए पूछते हैं। यहां कुछ संकेत दिए गए हैं कि यह क्या करता है: http://stackoverflow.com/questions/4948780/magic-numbers-in-boosthash-combine – pmr

+1

@Piotr: आप सुनिश्चित कर सकते हैं कि हैश अद्वितीय है। वास्तव में, यह गारंटी नहीं है _not_ अद्वितीय होने के कारण बस हैश मान में सभी संभावित सेटों का प्रतिनिधित्व करने के लिए पर्याप्त बिट्स नहीं हैं (जो अनंत है, कम से कम सैद्धांतिक रूप से)। यही कारण है कि आपको टक्कर का पता लगाने और उन्हें सही तरीके से संभालने के लिए 'ऑपरेटर ==' की भी आवश्यकता है। – Mat

5

आप boost::hash_range/boost::hash_combine (जो क्या PMR का जवाब होता है, प्रभावी रूप से), क्योंकि QSetstd::unordered_set के क्यूटी बराबर है, और, के रूप में के साथ qHash लागू नहीं कर सकते:

तो, अपने qHashCustom के लिए दिया एसटीएल नाम से पता चलता है, इन कंटेनरों अव्यवस्थित हैं, जबकि Boost Documentation कहा गया है कि hash_combine क्रम पर निर्भर है, यानी। यह अलग हैश मानों के लिए हैश क्रमपरिवर्तन होगा।

:

यह एक समस्या आप गारंटी नहीं दे सकते कि दो सेट है कि बराबर की तुलना कर रहे हैं वास्तव में, बराबर है, जो एक हैश समारोह की आवश्यकताओं में से एक है क्योंकि अगर आप भोलेपन से संग्रहीत क्रम में तत्वों हैश गठबंधन है

For all x, y: x == y => qHash(x) == qHash(y) 

इसलिए, यदि आपके हैश-संयोजन फ़ंक्शन को इनपुट मानों के किसी भी क्रमपरिवर्तन के लिए समान आउटपुट उत्पन्न करने की आवश्यकता है, तो इसे कम्यूटेटिव होना चाहिए।

template <typename T> 
inline uint qHash(const QSet<T> &set, uint seed=0) { 
    return std::accumulate(set.begin(), set.end(), seed, 
          [](uint seed, const T&value) { 
           return seed + qHash(value); // or^
          }); 
} 
संबंधित मुद्दे