2015-01-23 17 views
14

मैं जानता हूँ कि यह एक तार के साथ एक char शाब्दिक शृंखला आरंभ करने के लिए पूरी तरह से संभव है:क्या सशर्त रूप से चयनित स्ट्रिंग अक्षर के साथ एक वर्ण सरणी शुरू करना संभव है?

char arr[] = "foo"; 

सी ++ 11 8.5.2/1 इसलिए कहते हैं:

एक char सरणी (चाहे सादे char, signed char, या unsigned char), char16_t सरणी, char32_t सरणी, या wchar_t शाब्दिक शृंखला एक संकीर्ण चरित्र, char16_t स्ट्रिंग शाब्दिक, 0,123,053 से प्रारंभ किया जा सकता हैस्ट्रिंग शाब्दिक, या चौड़े स्ट्रिंग अक्षरशः, या ब्रेसिज़ में संलग्न एक उचित टाइप टाइपिंग स्ट्रिंग द्वारा। स्ट्रिंग अक्षर के मान के लगातार वर्ण सरणी के तत्वों को प्रारंभ करते हैं। ...

हालांकि, अगर आप एक सशर्त अभिव्यक्ति में दो स्ट्रिंग शाब्दिक साथ भी ऐसा ही कर सकते हैं? इस तरह उदाहरण के लिए:

char arr[] = MY_BOOLEAN_MACRO() ? "foo" : "bar"; 

(कहाँ MY_BOOLEAN_MACRO() एक 1 या 0 तक विस्तारित है)। ...

1 पहली अभिव्यक्ति प्रासंगिक रूप bool (खंड 4) में बदल जाती है:

सी ++ 11 5.16 (सशर्त ऑपरेटर) के प्रासंगिक भागों इस प्रकार हैं। इसका मूल्यांकन किया गया है और यदि यह true है, तो सशर्त अभिव्यक्ति का परिणाम दूसरी अभिव्यक्ति का मूल्य है, अन्यथा तीसरी अभिव्यक्ति का। ...

4 यदि दूसरा और तीसरा ऑपरेंड एक ही मूल्य श्रेणी के glvalues ​​हैं और एक ही प्रकार है, तो परिणाम उस प्रकार और मूल्य श्रेणी का है और यह दूसरा या तीसरा है तो यह थोड़ा सा क्षेत्र है ऑपरेंड एक बिट-फील्ड है, या यदि दोनों बिट-फ़ील्ड हैं।

ध्यान दें कि शाब्दिक एक ही लंबाई के हैं और इस प्रकार वे const char[4] प्रकार के दोनों प्रकार हैं।

GCC one ideone निर्माण स्वीकार करता है। लेकिन मानक पढ़ने से, मुझे यकीन नहीं है कि यह कानूनी है या नहीं। क्या किसी के पास बेहतर अंतर्दृष्टि है?

उत्तर

10

दूसरी ओर clang पर इस तरह के कोड (see it live) स्वीकार नहीं करता है और मेरा मानना ​​है कि clang इस (MSVC also rejects this code) पर सही है।

एक स्ट्रिंग शाब्दिक अनुभाग 2.14.5 में व्याकरण से परिभाषित किया गया है:

string-literal: 
    encoding-prefixopt" s-char-sequenceopt" 
    encoding-prefixoptR raw-string 

और इस खंड से पहले पैराग्राफ का कहना है (जोर मेरा):

एक स्ट्रिंग शाब्दिक वर्णों का अनुक्रम (जैसा कि 2.14.3 में परिभाषित किया गया है) डबल क्वा से घिरा हुआ है टीएस, वैकल्पिक रूप से आर, यू 8, यू 8 आर, यू, यूआर, यू, यूआर, एल, या एलआर, जैसा कि "...", आर "(...)", u8 "..." में पूर्ववर्ती है, u8R "(...)", यू "...", उर "~ (...) ~", यू "...", यू.आर. "zzz (...) zzz", एल "...", या एलआर "(...)", क्रमशः

और इसे आगे कहा गया है कि एक संकीर्ण स्ट्रिंग शाब्दिक के प्रकार है:

n स्थिरांक की

"सरणी चार ",

के साथ-साथ:

है स्थिर भंडारण अवधि

लेकिन एक स्थिर भंडारण अवधि के साथ, "n स्थिरांक चार की सरणी" एक स्ट्रिंग शाब्दिक के बाद से यह नहीं है नहीं है व्याकरण फिट करें और न ही यह अनुच्छेद 1 फिट करता है।

हम इस gcc पर असफल अगर हम एक गैर निरंतर अभिव्यक्ति (see it live) का उपयोग कर सकते हैं:

bool x = true ; 
char arr[] = x ? "foo" : "bar"; 

जो यह शायद एक विस्तार है इसका मतलब है, लेकिन यह गैर-अनुरूप है के बाद से यह नहीं है strict conformance mode यानी -std=c++11 -pedantic का उपयोग करके चेतावनी उत्पन्न करें। अनुभाग 1.4[intro.compliance] से:

[...] क्रियान्वयन प्रोग्राम हैं जो इस तरह के एक्सटेंशन है कि इस अंतर्राष्ट्रीय स्टैंडर्ड के अनुसार बीमार बनते हैं का उपयोग का निदान करने के लिए आवश्यक हैं। ऐसा करने के बाद, वे प्रोग्राम संकलित और निष्पादित कर सकते हैं।

+3

सहमत, 8.5.2/1 बहुत स्पष्ट लगता है कि यह * स्ट्रिंग शाब्दिक * है और नहीं * कुछ अभिव्यक्ति जो एक स्ट्रिंग शाब्दिक * का मूल्यांकन करती है। (भले ही आप इस मामले में एक स्ट्रिंग अक्षर के मूल्यांकन के रूप में टर्नरी ऑपरेटर पर विचार करें)। –

3

इस में जीसीसी में काम करता है सी ++ 11 या नए क्योंकि शाब्दिक प्रदान कर रहे हैं संकलन समय के दौरान नियतात्मक हैं (उदाहरण के लिए, वे constexpr हैं)। चूंकि संकलक यह पता लगा सकता है कि कौन सा सत्य है, इसे समझने की अनुमति है कि किस का उपयोग करना है।

, constexpr क्षमता को निकालने के लिए कुछ इस तरह का प्रयास करें:

#include <iostream> 
#include <cstdlib> 

int main() { 
    bool _bool = rand(); 
    char arr[] = (_bool) ? "asdf" : "ffff"; 

    std::cout << arr << std::endl; 
} 

जीसीसी तो साथ बाहर त्रुटियों:

g++ test.cpp -std=c++11 
test.cpp: In function ‘int main()’: 
test.cpp:6:34: error: initializer fails to determine size of ‘arr’ 
    char arr[] = (_bool) ? "asdf" : "ffff"; 
           ^
test.cpp:6:34: error: array must be initialized with a brace-enclosed initializer 

मैं मानक के पाठ परिभाषा काफी अच्छी तरह से पता करने के लिए पता नहीं है जहां या यह मान्य क्यों है, लेकिन मैं महसूस करता हूं कि यह मान्य है।

constexpr पर और पढ़ने के लिए और यह कैसे संगतता को प्रभावित कर सकता है, the answer by @ShafikYaghmour in another question देखें।

+1

ध्यान दें कि * निरंतर अभिव्यक्ति * और * constexpr * संबंधित हैं लेकिन समान नहीं हैं, मैं इसे कुछ डिग्री [यहां] (http://stackoverflow.com/a/26025026/1708801) पर कवर करता हूं, इसलिए 'gcc' इसका इलाज कर रहा है एक निरंतर अभिव्यक्ति। –

+0

सच है, मैं देख सकता हूं कि एक भेद है। लेकिन यह एक अच्छा मुद्दा है और मुझे नहीं लगता कि अंतर सी ++ 11 और उसके बाद में लागू होता है ... जब तक कि आप यह नहीं दिखा सकते कि यह करता है? – inetknght

+1

यह पूरी तरह से जानकारीपूर्ण है, उम्मीद है कि आपको यह उपयोगी लगेगा। मैं बस ध्यान दूंगा कि चूंकि प्रश्न टैग किया गया है भाषा-वकील लोग विवरण के बारे में अधिक पसंद करेंगे। –

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

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