2009-08-25 10 views
6

मैं कैसे हैश (std :: tr1 :: हैश या बूस्ट :: हैश) एक सी ++ पॉइंटर-टू-सदस्य-फ़ंक्शन कैसे कर सकता हूं?हैश कैसे करें और पॉइंटर-टू-सदस्य-फ़ंक्शन की तुलना करें?

उदाहरण:

मैं कई bool (कक्षा :: * functionPointer)() (स्थिर नहीं) वर्ग कक्षा के कई विभिन्न तरीकों के उस बिंदु है और मैं उन सूचक-टू-सदस्य-समारोह हैश करने के लिए की जरूरत है ।

मैं यह कैसे कर सकता हूं?

मैं उन सदस्य फ़ंक्शन पॉइंटर्स की तुलना (std :: less) की तुलना कैसे कर सकता हूं ताकि मैं उन्हें std :: set में संग्रहीत कर सकूं?

+7

वहाँ नहीं सामान्य रूप से एक सूचक हैश करने के लिए किसी भी कारण से, के रूप में यह बात आप उपयोग करना चाहते पर सीधे इशारा करता है।कृपया कुछ कोड प्रदान करें जो बताता है कि आप किस बारे में पूछ रहे हैं। –

+0

आप कब कहेंगे कि एक फ़ंक्शन पॉइंटर दूसरे की तुलना में 'कम' है? –

+0

@bojan: यदि तुलना का एकमात्र उद्देश्य उन्हें क्रमबद्ध सूची में संग्रहीत करना है, तो कोई भी निर्धारित आदेश होगा। उदाहरण के लिए बाइनरी मान। – erikkallen

उत्तर

13

सभी सी ++ ऑब्जेक्ट्स, जिसमें सदस्य फ़ंक्शंस के पॉइंटर्स शामिल हैं, को वर्णों की सरणी के रूप में स्मृति में दर्शाया गया है। तो अगर आप की कोशिश कर सकते:

bool (Class::*fn_ptr)() = &Class::whatever; 
const char *ptrptr = static_cast<const char*>(static_cast<const void*>(&fn_ptr)); 

अब (sizeof(bool (Class::*)())) बाइट्स की एक सरणी की ओर इशारा करते के रूप में ptrptr का इलाज, और हैश या उन बाइट्स की तुलना करें। यदि आप चाहें तो char के बजाय आप unsigned char का उपयोग कर सकते हैं।

यह कोई झूठी सकारात्मक गारंटी नहीं देता है - सी ++ 03 में, सदस्य कार्यों के पॉइंटर्स पीओडी हैं, जिसका मतलब है कि अन्य चीजों के बीच जिन्हें उन्हें memcpy का उपयोग करके कॉपी किया जा सकता है। इसका तात्पर्य है कि यदि समान बाइट-बाइट मान हैं, तो वे वही हैं।

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

यह संभावित रूप से कठिन है: सदस्य फ़ंक्शन पॉइंटर्स अजीब हैं, और स्टोरेज में किस प्रकार के फ़ंक्शन की ओर इशारा किया जाता है (आभासी, विरासत) के अनुसार अलग-अलग गैर-भाग लेने वाली "स्लैक स्पेस" शामिल होने की संभावना है। तो आपको शायद अपने कंपाइलर के कार्यान्वयन विवरण के साथ काफी महत्वपूर्ण बातचीत करनी होगी। यह आलेख आपको प्रारंभ करने में सहायता कर सकता है: http://www.codeproject.com/KB/cpp/FastDelegate.aspx

एक क्लीनर विकल्प आपके सभी फ़ंक्शन पॉइंटर्स को "कैनोनिकल" करने के लिए एक सरणी के माध्यम से एक रैखिक खोज करना पड़ सकता है, फिर तुलना करें और हैश "कैनोलिक" की स्थिति के आधार पर आपके सरणी में उस फ़ंक्शन पॉइंटर का उदाहरण। निर्भर करता है कि आपकी प्रदर्शन आवश्यकताओं क्या हैं। और यहां तक ​​कि यदि आवश्यकताएं हैं, तो कक्षा (और इसके व्युत्पन्न वर्गों) में इतने सारे कार्य हैं कि रैखिक खोज में कितना समय लगेगा?

typedef bool (Class::*func)(); 
vector<func> canon; 

size_t getIndexOf(func fn_ptr) { 
    vector<func>::iterator it = find(canon.begin(), canon.end(), fn_ptr); 
    if (it != canon.end()) return it - canon.begin(); 
    canon.push_back(func); 
    return canon.size() - 1; 
} 
+0

धन्यवाद char * चाल करता है! केवल मेरे कंपाइलर में मुझे static_cast के बजाय reinterpret_cast की आवश्यकता है। – AllDayCpp

+1

कुछ कांटेदार मुद्दों का +1, +1। यह मेरे लिए नहीं हुआ था कि pmf1 == pmf2 जरूरी नहीं कि बिटवाई पहचान को इंगित करे। –

+0

सदस्य फ़ंक्शन के लिए पॉइंटर में पैडिंग हो सकती है, जिसे समानता की तुलना करते समय अनदेखा किया जाएगा, और यादृच्छिक मान ले सकते हैं। किसी भी पैडिंग बाइट्स को हश करने से हैश फ़ंक्शन विफल हो जाएगा। –

0

मैं सूचक पिछले जवाब में वर्णित के रूप (Microsoft 2010 संकलक में) डाली नहीं कर सकता है, लेकिन यह मेरे लिए काम करता है:

static string fmptostr(int atype::*opt) 
    { 
     char buf[sizeof(opt)]; 
     memcpy(&buf,&opt,sizeof(opt)); 
     return string(buf,sizeof(opt)); 
    } 

सूचक की बिटवाइज़ पहचान के बारे में है, यह तो यह बिटवाइज़ किया जा सकता है ऐसा लगता है कि उपयुक्त कंपाइलर स्विच का उपयोग किया जाता है। कम से कम इस Microsoft संकलक उदा #pragma pointers_to_members और एक स्विच का उपयोग कर के लिए सच है .../VMG

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