2009-06-29 11 views
6

एसटीएल सी ++ hash_map का उपयोग करना ...stdext :: hash_map का उपयोग कैसे करें जहां कुंजी एक कस्टम ऑब्जेक्ट है?

class MyKeyObject 
{ 
    std::string str1; 
    std::string str2; 

    bool operator==(...) { this.str1 == that.str1 ... } 
}; 

class MyData 
{ 
    std::string data1; 
    int data2; 
    std::string etcetc; 
}; 

इस तरह ...

MyKeyObject a = MyKeyObject(...); 
MyData b = MyData(...); 

stdext::hash_map <MyKeyObject, MyData> _myDataHashMap; 
_myDataHashMap[ a ] = b; 

मैं त्रुटियों की एक पूरी लोड मिलता है। यहाँ पहले तीन ...

त्रुटि 1 त्रुटि C2784 हैं: 'bool std :: ऑपरेटर < (स्थिरांक std :: _ ट्री < _Traits> &, स्थिरांक std :: _ ट्री < _Traits> &) ': के लिए नहीं अनुमान टेम्पलेट तर्क सकता है' स्थिरांक MyKeyObject 'सी' से 'स्थिरांक std :: _ ट्री < _Traits> &: \ Program Files \ Microsoft दृश्य स्टूडियो 8 \ vc \ शामिल \ कार्यात्मक 143

01,235,

त्रुटि 2 त्रुटि C2784: 'bool std :: ऑपरेटर < (स्थिरांक std :: basic_string < _Elem, _Traits, _Alloc> &, स्थिरांक _Elem *)': 'स्थिरांक एसटीडी के लिए टेम्पलेट तर्क अनुमान नहीं कर सकता है: : basic_string < _Elem, _Traits, _Alloc> & 'से' स्थिरांक टास्किंग :: MyKeyObject 'C: \ Program फ़ाइलें \ माइक्रोसॉफ्ट विजुअल स्टूडियो 8 \ vc \ \ कार्यात्मक 143

त्रुटि 3 त्रुटि C2784 में शामिल हैं:' बूल std :: ऑपरेटर < (स्थिरांक _Elem *, स्थिरांक std :: basic_string < _Elem, _Traits, _Alloc> &) ': के लिए टेम्पलेट तर्क अनुमान नहीं कर सकता' स्थिरांक _Elem * 'से ' स्थिरांक MyDataObject 'C: \ Program फ़ाइलें \ Microsoft दृश्य स्टूडियो 8 \ vc \ शामिल \ 143

...

अगर मैं कुछ एक पूर्णांक की तरह साधारण के लिए कुंजी सेट सब कुछ ठीक है कार्यात्मक।

मैं क्या गलत कर रहा हूं ?! शायद मुझे टेम्पलेट्स के साथ कुछ करने की ज़रूरत है?

क्या इस तरह की कस्टम कुंजी ऑब्जेक्ट का उपयोग करके डेटा तक पहुंचने का एक बेहतर (तेज?) तरीका है?

+0

'hash_map' एक पुराने विस्तार है। Tr1 के 'unordered_map', या बूस्ट का उपयोग करें। – GManNickG

उत्तर

2

निम्नलिखित का प्रयास करें, वी.एस. 2005 में मेरे लिए काम किया यह निर्मित stdext नाम स्थान में hash_map प्रकार के साथ-साथ दोनों VS2005 के लिए एक समाधान है unordered_map (पसंदीदा) को बढ़ावा दें। जो भी आप उपयोग नहीं करते हैं उसे हटाएं।

#include <boost/unordered_map.hpp> 
#include <hash_map> 

class HashKey 
{ 
public: 
    HashKey(const std::string& key) 
    { 
     _key=key; 
    } 
    HashKey(const char* key) 
    { 
     _key=key; 
    } 

    // for boost and stdext 
    size_t hash() const 
    { 
     // your own hash function here 
     size_t h = 0; 
     std::string::const_iterator p, p_end; 
     for(p = _key.begin(), p_end = _key.end(); p != p_end; ++p) 
     { 
      h = 31 * h + (*p); 
     } 
     return h; 
    } 
    // for boost 
    bool operator==(const HashKey& other) const 
    { 
     return _key == other._key; 
    } 

    std::string _key; 
}; 

// for boost 
namespace boost 
{ 
    template<> 
    class hash<HashKey> 
    { 
    public : 
     std::size_t operator()(const HashKey &mc) const 
     { 
      return mc.hash(); 
     } 
    }; 
} 

// for stdext 
namespace stdext 
{ 
    template<> 
    class hash_compare<HashKey> 
    { 
    public : 
     static const size_t bucket_size = 4; 
     static const size_t min_buckets = 8; 

     size_t operator()(const HashKey &mc) const 
     { 
      return mc.hash(); 
     } 

     bool operator()(const HashKey &mc1, const HashKey &mc2) const 
     { 
      return (mc1._key < mc2._key); 
     } 
    }; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    { 
     stdext::hash_map<HashKey, int> test; 
     test["one"] = 1; 
     test["two"] = 2; 
    } 

    { 
     boost::unordered_map<HashKey, int> test(8); // optional default initial bucket count 8 
     test["one"] = 1; 
     test["two"] = 2; 
    } 

    return 0; 
} 
3

हैश तालिका का उपयोग करने के लिए, आपको हैश फ़ंक्शन निर्दिष्ट करने की आवश्यकता है। आपको फ़ंक्शन ऑब्जेक्ट बनाने की आवश्यकता है जो एक ऐसे फ़ंक्शन का प्रतिनिधित्व करता है जो MyKeyObject ऑब्जेक्ट लेता है और size_t देता है। तो फिर तुम प्रारंभिक आकार के बाद दूसरा तर्क के रूप में functor पारित:

hash_map <MyKeyObject, MyData> _myDataHashMap(initial_size, YourHashFunctor()); 

वैकल्पिक रूप से, आप अपने प्रकार के लिए hash<T> functor के टेम्पलेट विशेषज्ञता के रूप में अपने हैश समारोह लिख सकते हैं; इस तरह आपको एक कस्टम हैश फ़ंक्शन में पास करने की आवश्यकता नहीं है।

मुझे नहीं पता कि आप उन त्रुटियों को विशेष रूप से क्यों प्राप्त कर रहे हैं। शायद यह आपके ऑब्जेक्ट को हैश कोड या कुछ के रूप में उपयोग करने का प्रयास कर रहा है?किसी भी मामले में इसे हैश फ़ंक्शन के बिना काम नहीं करना चाहिए। हैश फ़ंक्शंस पूर्णांक प्रकारों और तारों के लिए पूर्व-परिभाषित हैं।

2

< लिंक हटाया गया> स्पष्ट रूप से बताता है कि हैश_मैप का उपयोग कैसे करें और अपना स्वयं का हैश फ़ंक्शन बनाएं।

(संपादित करें:। लिंक हटा दिया अब स्पैम पेज को अंक)

+0

जेनेरिक हैश फ़ैक्टर टेम्पलेट क्लास के टेम्पलेट विशेषज्ञता का उपयोग करने का बेहतर तरीका है। यह उदाहरण दिखाता है कि नक्शे के आरंभ में एक फ़ैक्टर ऑब्जेक्ट का उपयोग कैसे करें, लेकिन यह बोझिल एक सुरुचिपूर्ण है। – Marius

0

मैं शिखर डेटा की मैपिंग struct के लिए उपयोग कर रहा हूँ।

#include <stdio.h> 
#include <stdlib.h> 
#include <string> 
#include <boost/unordered_map.hpp> 



struct VERTEX 
{ 
float x,y,z; 
}; 

typedef boost::unordered_map<std::string, unsigned int> map; 

int main() 
{ 
VERTEX v1,v2,v3; 

v1.x = 5.0; v1.y = 2.0; v1.z = 2.33333336; 
v2.x = 5.0; v2.y = 2.0; v2.z = 2.32333336; 
v3.x = 5.0; v3.y = 2.0; v3.z = 2.33333336; 

unsigned int vertexSize = sizeof(VERTEX); 
char * v1c = new char[vertexSize]; 
char * v2c = new char[vertexSize]; 
char * v3c = new char[vertexSize]; 

memcpy(v1c, &v1, vertexSize);memcpy(v2c, &v2, vertexSize);memcpy(v3c, &v3, vertexSize); 
map mymap; 

std::string aaa(v1c, vertexSize); 
std::string bbb(v2c, vertexSize); 
std::string ccc(v3c, vertexSize); 

mymap[ aaa ] = 1; 
mymap[ bbb ] = 2; 

unsigned int a = mymap[ aaa ]; 
unsigned int b = mymap[ bbb ]; 
unsigned int c = mymap[ ccc ]; 


return 0; 
} 

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

0

मैं एक ही उत्तर खोजने की कोशिश करते हुए इस पुराने प्रश्न में आया हूं, और मौजूदा उत्तरों को वास्तव में उपयोगी नहीं ढूंढ पा रहा हूं। आजकल हम unordered_map का उपयोग करते हैं, यदि हम हैश मैप चाहते हैं, और सामान्य रूप से हैश_मैप में एक कुंजी के रूप में उपयोग करने योग्य MyKeyObject वर्ग बनाने का सबसे अच्छा तरीका कक्षा के लिए हैश फ़ंक्शन को परिभाषित करना है, और इस हैश फ़ंक्शन का उपयोग करने के लिए मानक लाइब्रेरी को बताएं नक्शे। इसका मतलब है कि हम हमेशा हैश फ़ंक्शन प्रदान किए बिना मानचित्र टेम्पलेट को तुरंत चालू कर सकते हैं।

wikipedia page 'सी ++ में अनियंत्रित सहयोगी कंटेनर' पर उदाहरण का पालन करना आसान है, मैंने इसे थोड़ा नीचे दबा दिया और इसे आपके मामले में लागू किया। पहले हम एक सदस्य पद्धति के रूप में एक सरल हैश फंक्शन को परिभाषित करेंगे:

#include <functional> 
class MyKeyObject { 
private: 
    std::string str1; 
    std::string str2; 

public: 
    inline size_t hash() const { 
     return std::hash<std::string>()(str1)^std::hash<std::string>()(str2); 
    } 

    inline bool operator==(const MyKeyObject& other) const { 
     return str1 == other.str1 && str2 == other.str2; 
    } 
}; 

आदेश हैश समारोह बनाने के लिए, हम XOR सभी के हैश एक साथ वस्तुओं निहित। यह std::hash का उपयोग करके किया जाता है, एक टेम्पलेट जिसे बच्चे के प्रकार के साथ तुरंत चालू किया जाना है। ध्यान दें कि हम इसे एक unordered_map पर तीसरे टेम्पलेट पैरामीटर के रूप में उपयोग नहीं कर सकते हैं। नोट भी कॉन्स-बराबर ऑपरेटर।

namespace std { 
    template <> 
    class hash<MyKeyObject> { 
    public: 
     size_t operator()(const MyKeyObject &aMyKeyObject) const { 
      return aMyKeyObject.hash(); 
     } 
    }; 
} 

यह std::hash टेम्पलेट वर्ग के लिए एक टेम्पलेट विशेषज्ञता कहते हैं, MyKeyObject के लिए हैश ऑपरेटर उपलब्ध कराने:

अब हम मानक पुस्तकालय है कि इस हैश फंक्शन MyKeyObject मूल्यों के लिए उपयोग किया जाता है यह बताने के लिए है कक्षा। उदाहरण नहीं है कि विकिपीडिया पेज सीधे हैश को परिभाषित करता है, बजाय हैश-फ़ंक्शन को कॉल करने के बजाय, जो ऑब्जेक्ट का सदस्य है - लेकिन यदि हैश फ़ंक्शन को निजी सदस्यों तक पहुंचना है, तो यह काम नहीं करेगा।

अब तुम इतनी तरह एक unordered_map में MyKeyObject उपयोग करने के लिए सक्षम होना चाहिए:

std::unordered_map<MyKeyObject, MyData> _myDataHashMap; 

(बजना/xcode के साथ परीक्षण)

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