2012-12-05 15 views
8

मैं एक सी ++ 11 समारोह है कि केवल एक पैरामीटर के रूप स्ट्रिंग शाब्दिक स्वीकार करेंगे लिखना चाहते हैं:सी ++ 11 फ़ंक्शन जो केवल स्ट्रिंग अक्षरों को स्वीकार करता है?

void f(const char* s) { static_assert(s is a string literal); ... } 

यही कारण है:

f("foo"); // OK 

char c = ...; 
f(&c); // ERROR: Doesn't compile 

string s = ...; 
f(s.c_str()); // ERROR: Doesn't compile 

etc 

वहाँ वैसे भी है इस लागू करने के लिए? फ़ंक्शन का हस्ताक्षर परिवर्तनों के लिए खुला है, क्योंकि मैक्रोज़ या किसी अन्य भाषा सुविधा का उपयोग जोड़ रहा है।

यदि यह संभव नहीं है तो निकटतम अनुमान क्या है? (क्या उपयोगकर्ता परिभाषित अक्षर किसी भी तरह से मदद कर सकते हैं?)

यदि जीसीसी 4.7/लिनक्स में कोई प्लेटफ़ॉर्म विशिष्ट तरीका नहीं है?

+0

स्ट्रिंग अक्षर के साथ आप क्या करेंगे जो आप गैर-स्ट्रिंग-अक्षर के साथ नहीं कर सकते हैं? और एक स्ट्रिंग अक्षर का उपयोग करके शुरू किया गया 'कॉन्स्ट char * const' चर गुजरने के बारे में कैसे? या एक स्ट्रिंग अक्षर के लिए एक 'कॉन्स चार (और सरणी) [] 'संदर्भ? – hvd

+2

यह संभव नहीं है, क्योंकि स्ट्रिंग अक्षर केवल 'char const [n]' arrays हैं, और जैसे कि उनसे अलग नहीं हैं। – Xeo

+0

हो सकता है कि उपयोगकर्ता द्वारा परिभाषित स्ट्रिंग अक्षर का उपयोग किया जा सके जो उस प्रकार को परिवर्तित करता है जिसमें डेटा केवल पढ़ने के लिए होता है जब यह एक रावल्यू संदर्भ होता है (इसलिए यह नामित चर नहीं हो सकता है)। लक्ष्य यह लागू करना है कि स्ट्रिंग शब्दशः कॉल के बिंदु पर कोड में टाइप की गई है, और स्थिर रूप से एप्लिकेशन छवि में संकलित है। –

उत्तर

12

मुझे लगता है कि सबसे करीब आप प्राप्त करने के लिए जा रहे हैं इस

template<int N> 
void f(const char (&str)[N]){ 
    ... 
} 

यह शाब्दिक और सरणियों लेकिन नहीं संकेत के साथ संकलन होगा।

+0

आप इसे 'std :: enable_if <>' के चालाक उपयोग के साथ अधिकांश गैर-शाब्दिक सरणी के साथ काम करने से रोकने में सक्षम हो सकते हैं। Enable_if में क्या रखना है इसके उदाहरण के लिए http://stackoverflow.com/questions/14805011/how-to-detect-a-string-literal-with-type-traits देखें (हालांकि वह प्रश्न static_assert का उपयोग करता है, यह वही है अवधारणा)। – wjl

3

एक विकल्प संभवतः जीसीसी एक्सटेंशन को संकलित समय पर जांचने के लिए किया जा सकता है कि आपका विशेष फ़ंक्शन केवल शाब्दिक स्ट्रिंग के साथ बुलाया जाता है।

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

असल में, आप जीसीसी के अंदर एक नया पास जोड़ देंगे और एमईएलटी में जो कोड गुजरता है, जो आपके काम पर कॉल करने वाले प्रत्येक गिंपल को मिलेगा और जांच करेगा कि तर्क वास्तव में एक शाब्दिक स्ट्रिंग है। ex06 उदाहरण melt-examples पर आपको प्रेरित करना चाहिए। फिर [email protected] की सदस्यता लें और अपने एमईएलटी विशिष्ट प्रश्न पूछें।

बेशक, यह मूर्खतापूर्ण दृष्टिकोण नहीं है: फ़ंक्शन को पॉइंटर्स के माध्यम से परोक्ष रूप से कहा जा सकता है, और यह उदा। आंशिक शाब्दिक स्ट्रिंग है, उदा। f("hello world I am here"+(i%4)) अवधारणात्मक रूप से कुछ शाब्दिक स्ट्रिंग के साथ एक कॉल है (उदा। .rodata सेगमेंट में), लेकिन जेनरेट कोड में और न ही दंपति में।

1

मैं इस का उपयोग करें:

// these are used to force constant, literal strings in sqfish binding names 
// which allows to store/copy just the pointer without having to manage 
// allocations and memory copies 
struct _literalstring 
{ 
    // these functions are just for easy usage... not needed 
    // the struct can be empty 
    bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); } 
    bool equal(const char *other) { return !strcmp((const char *)this, other); } 
    const char *str(void) { return (const char *)this; } 
    bool empty(void) { return *(const char *)this == 0; } 
}; 

typedef _literalstring *LITSTR; 

constexpr LITSTR operator "" _LIT(const char *s, size_t) { 
    return (LITSTR)s; 
} 

तो फिर तुम सिर्फ इस तरह अपने कार्य की घोषणा:

void myFunc(LITSTR str) 
{ 
    printf("%s\n", str->str()); 
    printf("%s\n", (const char *)str); 
    const char *aVar = str->str(); 
    const char *another = (const char *)str; 
} 

और आप इसे इस तरह कहते हैं:

myFunc("some text"_LIT); 

आप कुछ करते हैं इस तरह:

myFunc("some text"); 
myFunc(aTextVariable); 

आपको एक कंपाइलर त्रुटि मिलती है।

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