2016-12-13 8 views
17

निम्नलिखित स्निपेट पर विचार करें?
इसका व्याख्या कैसे किया जाता है?{} में शून्य {{}) क्या है?</p> <pre><code>auto f() { return void({}); } int main() { f(); } </code></pre> <p>वास्तव में क्या <code>void({})</code> में <code>{}</code> है:

बिल्कुल जिज्ञासा से बाहर। चलो कुछ और आगे जाओ।

ध्यान दें कि दोनों जीसीसी 6.1 और क्लैंग 3.8 दोनों त्रुटियों (-std=c++14 -pedantic) के साथ संकलित करते हैं।

चेतावनी:
बाद में शिकायत नहीं है, पूर्व में एक चेतावनी से पता चलता गैर वर्ग प्रकार के लिए सूची-प्रारंभकर्ता

parenthesized नहीं किया जाना चाहिए बजाय -pedantic-errors का उपयोग करना, जीसीसी एक त्रुटि के साथ समाप्त होता है जबकि क्लैंग इसे संकलित करता है।

क्या यह विसंगति दो कंपाइलरों में से एक की त्रुटि है?
मेरा मतलब है, क्या यह वैध कोड है जिसे स्वीकार किया जाना चाहिए या नहीं?

+1

कुछ भाषाओं में, यह एक खाली तालिका या सूची को दर्शाता है। हालांकि, टाइप आधारित भाषाओं में, इसमें एक प्रकार का विनिर्देश होना चाहिए। प्रारंभकर्ता होने के साथ इसका कोई संबंध नहीं है, इसलिए आईएमओ, यह कुछ प्रकार के रिक्त ब्लॉक स्कोप की तरह दिखता है। – Chemistpp

+0

एक क्लैंग बग की तरह लगता है। यह [\ [expr.type.conv \]/2] पर जाता है (https://timsong-cpp.github.io/cppwp/expr.type.conv#2) "अन्यथा, अभिव्यक्ति का एक प्रकोप है निर्दिष्ट प्रकार जिसका परिणाम ऑब्जेक्ट प्रारंभिक के साथ प्रत्यक्ष-प्रारंभिक ([dcl.init]) है। ", जो 'शून्य' के लिए कोई समझ नहीं लेता है। –

+0

यह लैम्ब्डा अभिव्यक्ति के रूप में दिखता है: [link] (http://en.cppreference.com/w/cpp/language/lambda) – Raindrop7

उत्तर

15

void रूपांतरणों के साथ-साथ void मान को वापस करने की संभावना बहुत ही शुरुआत से सी ++ भाषा में मौजूद है। प्रश्नों को उठाते हुए एकमात्र हिस्सा इस संदर्भ में {} की भूमिका है।

बजना

int a({}); 

के साथ एक त्वरित प्रयोग

error: cannot initialize a variable of type 'int' with an rvalue of type 'void' 

जो कि बजना इंगित करता है एक void मूल्य के रूप में {} की व्याख्या करते हुए कहा एक त्रुटि संदेश उत्पन्न करता है। यह एक गैर-मानक व्यवहार प्रतीत होता है। मुझे भाषा विनिर्देश में कोई स्थान नहीं दिखता है जो कहता है कि {} को इस संदर्भ में void मान का उत्पादन करना चाहिए।

लेकिन चूंकि यह क्लैंग में मामला होता है, इसलिए void({}) में क्लैंग में संकलन में असामान्य कुछ भी नहीं है। सी ++ में किसी भी मूल्य को void प्रकार में परिवर्तित किया जा सकता है, जिसका अर्थ यह है कि जब तक संकलक {} को इस संदर्भ में स्वीकार करता है, तो बाकी स्वाभाविक रूप से पालन करता है।

जीसीसी में यह वास्तव में -pedantic-errors मोड में कोई त्रुटि है

error: list-initializer for non-class type must not be parenthesized 

तो औपचारिक रूप से यह एक "त्रुटि", नहीं एक "चेतावनी" जीसीसी में है।


क्या वास्तव में यहाँ होता है कि उद्घाटन ({ और }) बंद करने के संयोजन Statement Expression के रूप में जाना एक जीएनयू सी भाषा एक्सटेंशन (जो संयोग से रूप में अच्छी तरह बजना द्वारा समर्थित है) के रूप में यह व्याख्या करने के लिए इन compilers बना देता है।यह वही है निम्नलिखित कोड संकलन

int a = ({ 3; }); 

कि विस्तार के तहत बना देता है, अभिव्यक्ति ({})void प्रकार के एक बयान अभिव्यक्ति के रूप में देखा जाता है, उदाहरण के लिए है। हालांकि, यह सी ++ में समान प्रारंभिक वाक्यविन्यास के साथ संघर्ष करता है।

+1

क्लैंग ट्रंक अब इस मामले के लिए एक जीसीसी जैसे त्रुटि संदेश उत्पन्न करता है (चूंकि [इस नवंबर] (https://reviews.llvm.org/D25816))। –

+0

... और [यह खुशी से ओपी के कोड का भी निदान करता है] (http://melpon.org/wandbox/permlink/fyypiO2iebe2xE2B)। –

+1

@ टी.सी. और यह मेरी गलती है कि यह ट्रंक के खिलाफ कोशिश नहीं की है। धन्यवाद। – skypjack

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