2013-04-07 13 views
24

के लिए स्ट्रिंग शाब्दिक उपयोग करने के लिए मैं constexpr का उपयोग करके int को const char* कास्ट करने के लिए कुछ कोड लिखा है और इस तरह मैं एक टेम्पलेट तर्क के रूप में एक const char* उपयोग कर सकते हैं। यहाँ कोड है:"constexpr" का उपयोग टेम्पलेट पैरामीटर

#include <iostream> 

class conststr 
{ 
    public: 
     template<std::size_t N> 
     constexpr conststr(const char(&STR)[N]) 
     :string(STR), size(N-1) 
     {} 

     constexpr conststr(const char* STR, std::size_t N) 
     :string(STR), size(N) 
     {} 

     constexpr char operator[](std::size_t n) 
     { 
      return n < size ? string[n] : 0; 
     } 

     constexpr std::size_t get_size() 
     { 
      return size; 
     } 

     constexpr const char* get_string() 
     { 
      return string; 
     } 

     //This method is related with Fowler–Noll–Vo hash function 
     constexpr unsigned hash(int n=0, unsigned h=2166136261) 
     { 
      return n == size ? h : hash(n+1,(h * 16777619)^(string[n])); 
     } 

    private: 
     const char* string; 
     std::size_t size; 
}; 

// output function that requires a compile-time constant, for testing 
template<int N> struct OUT 
{ 
    OUT() { std::cout << N << '\n'; } 
}; 

int constexpr operator "" _const(const char* str, size_t sz) 
{ 
    return conststr(str,sz).hash(); 
} 

int main() 
{ 
    OUT<"A dummy string"_const> out; 
    OUT<"A very long template parameter as a const char*"_const> out2; 
} 

इस उदाहरण कोड में, out के प्रकार OUT<1494474505> और की out2OUT<106227495> है प्रकार है। इस कोड के पीछे जादू conststr::hash() है यह constexpr रिकर्सन है जो FNV Hash function का उपयोग करता है। और इस प्रकार यह कॉन्स char * के लिए एक अभिन्न हैश बनाता है जो उम्मीद है कि एक अद्वितीय है।

  1. यह एक सुरक्षित दृष्टिकोण का उपयोग करने है:

    मैं इस विधि के बारे में कुछ सवाल हैं? या यह दृष्टिकोण एक विशिष्ट उपयोग में एक बुराई हो सकता है?
  2. क्या आप एक बेहतर हैश फ़ंक्शन लिख सकते हैं जो प्रत्येक स्ट्रिंग के लिए कई वर्णों तक सीमित किए बिना अलग पूर्णांक बनाता है? (मेरे विधि में, लंबाई काफी लंबे समय है)
  3. आपको एक कोड है कि परोक्ष conststr के माध्यम से int constexpr करने के लिए const char* डाले लिख सकते हैं और इस प्रकार हम सौंदर्य की दृष्टि से बदसूरत (और यह भी समय उपभोक्ता) _const उपयोगकर्ता परिभाषित स्ट्रिंग शाब्दिक की जरूरत नहीं होगी? उदाहरण के लिए OUT<"String"> कानूनी होगा (और पूर्णांक में "स्ट्रिंग" कास्ट करें)।

किसी भी मदद की सराहना की जाएगी, बहुत बहुत धन्यवाद।

+0

मेरा उत्तर आपके प्रश्न 'का समाधान करता है', तो यह रूप में स्वीकार चिह्नित कर सकते हैं? अन्यथा, आप इसे टिप्पणी कर सकते हैं (दोबारा)! – Synxis

+0

ओह, मेरी माफी, मैं हमेशा ऐसा करना भूल जाता हूं :) –

उत्तर

11

हालांकि आपकी विधि बहुत रोचक है, लेकिन यह वास्तव में टेम्पलेट तर्क के रूप में एक स्ट्रिंग अक्षर को पारित करने का एक तरीका नहीं है। वास्तव में, यह स्ट्रिंग शाब्दिक के आधार पर टेम्पलेट तर्क का जनरेटर है, जो समान नहीं है: आप hashed_string से पुनर्प्राप्त नहीं कर सकते हैं ... यह टेम्पलेट्स में स्ट्रिंग अक्षर के पूरे हित को हरा देता है।

EDIT: निम्नलिखित सही था जब हैश का उपयोग अक्षरों के भारित योग था, जो ओपी के संपादन के बाद मामला नहीं है।

मिटchnल के उत्तर के अनुसार, आपको hash function के साथ भी समस्याएं हो सकती हैं। यह आपकी विधि, टकराव के साथ एक और बड़ी समस्या हो सकती है। उदाहरण के लिए:

// Both outputs 3721 
OUT<"0 silent"_const> out; 
OUT<"7 listen"_const> out2; 

जहाँ तक मुझे पता है, आप एक स्ट्रिंग सीधी वर्तमान मानक में एक टेम्पलेट तर्क में शाब्दिक पारित नहीं कर सकते हैं। हालांकि, आप इसे "नकली" कर सकते हैं।

template<typename str> 
struct out 
{ 
    out() 
    { 
     std::cout << str::asString() << "\n"; 
    } 
}; 

EDIT2:: मैं "नकली स्ट्रिंग शाब्दिक" एक प्रकार तर्क के माध्यम से गुजरती हैं, तो

struct string_holder    // 
{         // All of this can be heavily optimized by 
    static const char* asString() // the compiler. It is also easy to generate 
    {        // with a macro. 
     return "Hello world!"; // 
    }        // 
};        // 

: यहाँ है कि मैं क्या सामान्य रूप में उपयोग करते हैं आप टिप्पणी आप इस प्रयोग किया जाता भेद करने में कहा एक वर्ग टेम्पलेट के कई विशेषज्ञताओं के बीच। विधि आप से पता चला कि के लिए मान्य है, लेकिन आप यह भी टैग का उपयोग कर सकते हैं:

// tags 
struct myTag {}; 
struct Long {}; 
struct Float {}; 

// class template 
template<typename tag> 
struct Integer 
{ 
    // ... 
}; 
template<> struct Integer<Long> { /* ... */ }; 

// use 
Integer<Long> ...; // those are 2 
Integer<Float> ...; // different types 
+0

सिंक्सिस, मैंने अपना कोड संपादित किया। मेरा हैश फ़ंक्शन एक गैर-व्यावसायिक था, अब यह फाउलर-नोल-वो हैश फ़ंक्शन का उपयोग कर रहा है। मेरा मानना ​​है कि इस समारोह में एक ही समस्या नहीं है। और मैं आपके पहले पैराग्राफ को समझ नहीं पाया कि 'hashed' से 'hashed' के बारे में? –

+1

आप स्ट्रिंग को 'आउट' पर पास नहीं करते हैं, लेकिन 'हैश() 'का परिणाम नहीं है। मुझे नहीं लगता कि आप इस मान को एक स्ट्रिंग में बदल सकते हैं ... इसलिए, आप ब्रैकेट के बीच लिखे गए स्ट्रिंग को आउटपुट नहीं कर सकते हैं। – Synxis

+0

ओह मैं देखता हूँ। असल में यह मेरे लिए कोई समस्या नहीं है (बेशक आपका बिंदु मान्य है) क्योंकि मैं ऐसे टेम्पलेट्स बनाना चाहता हूं जो इस तरह काम करते हैं: मान लें कि हमारे पास इंटीजर <>, इंटीजर <"long"> नामक एक टेम्पलेट है जो इंटीजर <"short"> से कुछ अलग होगा और मैं विशेषज्ञ ऐसा करने के लिए मेरा टेम्पलेट। –

6

यहाँ पैटर्न है कि मैं टेम्पलेट स्थिरांक स्ट्रिंग पैरामीटर के लिए उपयोग कर रहा हूँ है। class F { static constexpr const char conststr[]= "some const string"; TemplateObject<conststr> instance; };

देखें: https://stackoverflow.com/a/18031951/782168

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