सी ++ में, यदि फेंक एक अभिव्यक्ति है, तो इसका प्रकार क्या है?


115

मैंने इसे अपने संक्षिप्त विवरणों में से एक में उठाया है:

http://www.smallshire.org.uk/sufficientlysmall/2009/07/31/in-c-throw-is-an-expression/

मूल रूप से, लेखक बताते हैं कि C ++ में:

throw "error"

अभिव्यक्ति है। यह वास्तव में मुख्य पाठ और व्याकरण दोनों में सी ++ मानक में स्पष्ट रूप से स्पष्ट रूप से वर्तनी है। हालाँकि, जो स्पष्ट नहीं है (मेरे लिए कम से कम) वह क्या है जो अभिव्यक्ति का प्रकार है? मैंने अनुमान लगाया " void", लेकिन जी ++ 4.4.0 और कोमू के साथ प्रयोग करने के एक बिट ने इस कोड को उत्पन्न किया:

    void f() {
    }

    struct S {};

    int main() {
        int x = 1;
        const char * p1 = x == 1 ? "foo" : throw S();  // 1
        const char * p2 = x == 1 ? "foo" : f();        // 2
    }

संकलकों को // 1 के साथ कोई समस्या नहीं थी, लेकिन // 2 पर बारफेड किया गया क्योंकि सशर्त ऑपरेटर के प्रकार अलग-अलग हैं। तो एक throwअभिव्यक्ति का प्रकार शून्य नहीं लगता है।

तो यह क्या है?

यदि आप जवाब देते हैं, तो कृपया मानक से उद्धरणों के साथ अपने बयान वापस लें।


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

c++  throw 

10
+1 बहुत बढ़िया सवाल। और इसका परीक्षण करने का एक चतुर तरीका है।
जेरेमी पॉवेल

1
यह लिंक स्पष्ट रूप से स्पष्ट करने के लिए लगता है कि प्रकार को कंपाइलर द्वारा निर्धारित किया जाता है कि यह जो भी होना चाहिए।
ड्रेमन जूल

मेरे द्वारा देखे जाने के बाद से जुड़ा हुआ लेख मुझे लगता है कि अपडेट हो गया है, और मुझे यकीन है कि वास्तव में ऐसा ही है। हालाँकि, मुझे यह मानक में नहीं मिला।

और शायद नहीं - डबल डी = "फू" फेंकना; साथ जी + = एक त्रुटि है (comeau साथ यह परीक्षण नहीं किया)

+1 जवाब जानने के लिए उत्सुक हूं।
आरा

जवाबों:


96

मानक के अनुसार, 5.16 पैरा 2 पहला बिंदु, "दूसरा या तीसरा ऑपरेंड (लेकिन दोनों नहीं) एक फेंक-अभिव्यक्ति (15.1) है, परिणाम दूसरे के प्रकार का है और एक प्रतिद्वंद्विता है।" इसलिए, सशर्त ऑपरेटर परवाह नहीं करता है कि फेंक-अभिव्यक्ति किस प्रकार की है, लेकिन सिर्फ दूसरे प्रकार का उपयोग करेगा।

वास्तव में, 15.1, पैरा 1 स्पष्ट रूप से कहता है "एक फेंक-अभिव्यक्ति टाइप शून्य है।"


9
ठीक है - मुझे लगता है कि हमारे पास एक विजेता है।

ध्यान दें कि थ्रो-एक्सप्रेशन असाइनमेंट-एक्सप्रेशन हैं। इसलिए वे अधिकांश ऑपरेटरों के तर्क के रूप में एक वाक्यविन्यास त्रुटि हैं। जाहिर है, आप उन्हें कोष्ठक में छिपा सकते हैं, लेकिन अगर उन्हें अनदेखा नहीं किया गया है (उदाहरण के लिए, बिलिन ऑपरेटर का पहला तर्क), तो यह एक प्रकार की त्रुटि है।
एपीग्रामग्राम

4
वास्तव में मुझे आश्चर्य होता है कि उन्होंने इस मामले के बारे में सोचा और कुछ उचित किया।
ओमनिफरियस

31

"थ्रो-एक्सप्रेशन टाइप शून्य है"

ISO14882 धारा 15


फिर दोनों g ++ और Comeau मेरे // 1 केस के लिए कोई त्रुटि नहीं देने के लिए रिमिस हैं?

2
@ नील, वास्तव में नहीं क्योंकि C ++ / 5.16 / 2 के अनुसार, सशर्त ऑपरेटर का दूसरा और तीसरा ऑपरेंड प्रकार का हो सकता हैvoid
mloskot

13

[Expr.cond.2] (सशर्त ऑपरेटर ?:) से:

यदि या तो दूसरे या तीसरे ऑपरेंड में टाइप (संभवतः cv-quali v ed) शून्य है, तो दूसरे और तीसरे ऑपरेंड पर lvalue-to-rvalue, array-to-pointer, और function-to-pointer मानक रूपांतरण किया जाता है और निम्नलिखित में से एक धारण करेगा:

- दूसरा या तीसरा ऑपरेंड (लेकिन दोनों नहीं) एक फेंक-अभिव्यक्ति है; परिणाम दूसरे के प्रकार का होता है और यह एक प्रतिद्वंद्विता है।

- दूसरे और तीसरे दोनों ऑपरेंड्स में टाइप शून्य है; परिणाम प्रकार शून्य है और एक प्रतिद्वंद्विता है। [नोट: इसमें वह मामला शामिल है जहां दोनों ऑपरेंड थ्रो-एक्सप्रेशन हैं। - अंतिम नोट]

इसलिए, जब //1आप पहले मामले में //2थे, तो आप "निम्नलिखित में से एक को पकड़ेंगे" का उल्लंघन कर रहे थे, क्योंकि उनमें से कोई भी उस मामले में ऐसा नहीं करता था।


3

आपके लिए एक प्रकार का प्रिंटर थूक हो सकता है :

template<typename T>
struct PrintType;

int main()
{
    PrintType<decltype(throw "error")> a; 
}

मूल रूप से कार्यान्वयन की कमी के PrintTypeकारण संकलन त्रुटि रिपोर्ट का कारण होगा:

अपरिभाषित टेम्पलेट के निहित तात्कालिकता PrintType<void>

इसलिए हम वास्तव में यह सत्यापित कर सकते हैं कि throwभाव प्रकार के हैं void(और हाँ, अन्य उत्तरों में उल्लिखित मानक उद्धरण सत्यापित करते हैं कि यह कार्यान्वयन विशिष्ट परिणाम नहीं है - हालाँकि gcc में एक कठिन समय है बहुमूल्य जानकारी को मुद्रित करना)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.