2011-02-12 14 views
12

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

मैंने संकलन समय में स्ट्रिंग के हैश-योग की गणना के लिए एल्गोरिदम के लिए गुगल किया है: C++ compile-time string hashing with Boost.MPL

यह मेरी समस्या का एकदम सही समाधान प्रतीत होता है, सिवाय इसके कि सिरिंज जो एल्गोरिदम के लिए आवश्यक है, स्पष्ट कारणों से, 4 वर्णों, या चरित्र-दर-चरित्र के साथ टुकड़ों में विभाजित किया जाना चाहिए।

अर्थात, पहचान पत्र के सामान्य मौजूदा रिकॉर्ड के बजाय, मैं इस तरह से लिखने के लिए होगा:

hash_cstring<boost::mpl::string<'obje', 'ct.m', 'etho', 'd'>>::value 

यह बिल्कुल बेकार है।

सवाल यह है कि इस एल्गोरिदम में "object.method" जैसे स्ट्रिंग को सही ढंग से कैसे पास किया जाए?

सभी को धन्यवाद।

+1

क्या आप सीधे स्ट्रिंग के बजाय स्थिर स्ट्रिंग के साथ संरचना का उपयोग कर सकते हैं? शायद उन्हें उत्पन्न करने के लिए एक मैक्रो भी? – Anycorn

+1

@aaa: मैक्रोज़ टोकन को विभाजित नहीं करते हैं, वे उन्हें स्ट्रिंग या समेकित कर सकते हैं, लेकिन उन्हें विभाजित नहीं कर सकते हैं। नाम और स्थिर स्ट्रिंग के साथ संरचना उत्पन्न करने के लिए –

+0

@ मैट मैक्रोज़। उदाहरण के लिए '#define str (n) struct n {...} ' – Anycorn

उत्तर

7

जीसीसी-4.6 के साथ समाधान:

#include <iostream> 
template<size_t N, size_t I=0> 
struct hash_calc { 
    static constexpr size_t apply (const char (&s)[N]) { 
     return (hash_calc<N, I+1>::apply(s)^s[I]) * 16777619u; 
    }; 
}; 

template<size_t N> 
struct hash_calc<N,N> { 
    static constexpr size_t apply (const char (&s)[N]) { 
     return 2166136261u; 
    }; 
}; 

template<size_t N> 
constexpr size_t hash (const char (&s)[N]) { 
    return hash_calc<N>::apply(s); 
} 

int main() { 
    char a[] = "12345678"; 
    std::cout << std::hex << hash(a) << std::endl; 
    std::cout << std::hex << hash("12345678") << std::endl; 
} 

http://liveworkspace.org/code/DPObf

मैं `खुश!

+0

क्या आप वास्तव में रिक्त त्रुटि के बिना जीसीसी 4.6 के साथ संकलित करने के लिए इसे प्राप्त कर रहे हैं? – Damon

+0

हां, सब ठीक काम करता है। जीसीसी-4.6.0, 4.6.1, 4.6.2, 4.7.0। – niXman

+0

मजेदार, मेरा जीसीसी-4.6.1 (मिंगडब्लू-टीडीएम) उस कोड को उस त्रुटि से अस्वीकार करता है (यही कारण है कि मैंने पूछा)। – Damon

5

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

1

टेम्पलेट्स किसी भी बाहरी प्रतीक के साथ instantiated जा सकता है, इसलिए इस अपेक्षा के अनुरूप काम करना चाहिए:

external char const* object_method = "object.method"; 
... = hash_cstring<object_method>::value; 

(टेम्पलेट hash_cstring<> दिया सूचक मूल्यों के साथ सौदा करने में सक्षम है)।

0

मामले में किसी को भी रुचि रखता है, मैं कैसे सी ++ 11 constexpr कार्य करता है और यहाँ variadic टेम्पलेट का उपयोग कर Murmur3_32 का एक संकलन समय हैश बनाने के लिए के माध्यम से चलना:

http://roartindon.blogspot.sg/2014/10/compile-time-murmur-hash-in-c.html

उदाहरण मैंने के अधिकांश हैश के साथ सौदा देखा गया है जो एक समय में स्ट्रिंग के एक चरित्र का उपभोग करने पर आधारित होता है। Murmur3_32 हैश एक और अधिक रोचक है कि यह एक समय में 4 वर्णों का उपभोग करता है और शेष 0, 1, 2 या 3 बाइट्स को संभालने के लिए कुछ विशेष केस कोड की आवश्यकता होती है।

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