2011-10-31 16 views
7

निम्नलिखित कोड जी ++ 4.6.1 के साथ संकलित है, लेकिन दृश्य स्टूडियो 2008फेंक और सी में त्रिगुट ऑपरेटर ++

return (m_something == 0) ? 
    throw std::logic_error("Something wrong happened") : m_something; 

तथ्य दृश्य स्टूडियो संकलक एक आंतरिक दुर्घटना करता है के साथ नहीं।

मैं जानना चाहता हूं कि यह मानक सी ++ है और क्यों यह विजुअल स्टूडियो के साथ संकलित नहीं होता है, लेकिन जी ++ के साथ करता है?

+8

मानक, जब एक संकलक के अनुसार एक आंतरिक कंपाइलर त्रुटि के साथ दुर्घटनाओं (जो वीसी करता है, IIUC), तो यह संकलक में एक त्रुटि है। एक कंपाइलर को दोषपूर्ण कोड के लिए भी एक सार्थक संदेश उत्सर्जित करना है, क्रैश रिपोर्ट नहीं। – sbi

+0

ध्यान रखें कि यह * सशर्त ऑपरेटर * है, जो * ए * टर्नरी ऑपरेटर होता है। – GManNickG

+0

हाँ, भ्रमित हो गया जब "टर्नरी" कहीं भी कल्पना में नहीं था। –

उत्तर

11

यह मानक सी ++ है। एक सशर्त अभिव्यक्ति में तत्कालीन/अन्य अभिव्यक्तियों के या तो (या दोनों) को इसके बजाय फेंक-अभिव्यक्ति (सी ++ 98 5.16/2) होने की अनुमति है।

यदि विज़ुअल स्टूडियो इसे संकलित करते समय क्रैश हो जाता है ... जो दुर्भाग्यपूर्ण प्रतीत होता है!

+1

§5.16/2 दोनों अभिव्यक्तियों को C++ 11 में अभिव्यक्तियों को फेंकने की अनुमति देता है। – Mat

+0

@ मेट: ओह, आप बिल्कुल सही हैं, यहां टेक्स्ट अपरिवर्तित है, और दूसरा विकल्प सी ++ 98 में भी फेंकने की अनुमति देता है। –

4

Comeau त्रुटियों के बिना यह संकलित (यहाँ मेरी कम से कम compilable परीक्षण का मामला है):

int main(void) 
{ 
    int x = 17; 
    return x ? throw "Something wrong happened" : 5; 
} 

जो काफी अच्छा सबूत है कि यह मानक द्वारा दी जाने वाली अनुमति है। तो यह तथ्य है कि एक त्रुटि के साथ साफ-सफाई में विफल होने के बजाय, एमएसवीसी दुर्घटनाग्रस्त हो जाता है।

इसके अलावा, यह कुलपति ++ 2010

R:\>cl ternarythrowtest.cpp 
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86 
Copyright (C) Microsoft Corporation. All rights reserved. 

ternarythrowtest.cpp 
Microsoft (R) Incremental Linker Version 10.00.40219.01 
Copyright (C) Microsoft Corporation. All rights reserved. 

/out:ternarythrowtest.exe 
ternarythrowtest.obj 

और x64 संस्करण में ठीक किया गया प्रतीत होता है:

R:\>cl ternarythrowtest.cpp 
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64 
Copyright (C) Microsoft Corporation. All rights reserved. 

ternarythrowtest.cpp 
Microsoft (R) Incremental Linker Version 10.00.40219.01 
Copyright (C) Microsoft Corporation. All rights reserved. 

/out:ternarythrowtest.exe 
ternarythrowtest.obj 

यदि संभव हो तो अपने संकलक अपग्रेड, यह केवल बग 2010

में तय से दूर है
+0

दरअसल, यह शायद सी ++ 11 अनुपालन के कारण है, @ म्यूइंग डक का जवाब देखें। –

+1

@ एंड्रिकॉन: यह "आंतरिक कंपाइलर त्रुटि" को समझाने में विफल रहता है। और जॉन के जवाब को देखें, इसे सी ++ 98 में भी अनुमति है। –

+0

मैं @ फोरमन्सी की टीम पर हूं, और मैं वह हूं जिसने माइक्रोसॉफ्ट कंपाइलर दुर्घटना का सामना अपने फेंक-इन-ए-टर्नरी-ऑपरेटर अभिव्यक्ति के साथ किया था। हम यह पता लगाने की कोशिश कर रहे थे कि यह मानक था, न कि यह माइक्रोसॉफ्ट के कंपाइलर में एक बग है (स्पष्ट रूप से * ए * बग है, क्योंकि यह दुर्घटनाग्रस्त है)। –

3

सी ++ 11 फरवरी ड्राफ्ट

§ 5.16/2 से या तो दूसरे या तीसरे संकार्य टाइप है (संभवतः सीवी-योग्य) शून्य है, तो lvalue करने वाली rvalue (4.1) , सरणी-टू-पॉइंटर (4.2), और फ़ंक्शन-टू-पॉइंटर (4.3) मानक रूपांतरण दूसरे और तीसरे ऑपरेटरों पर किए जाते हैं, और इनमें से एक निम्न रखेगा:
- दूसरा या तीसरा ऑपरेंड (लेकिन नहीं दोनों) एक फेंक अभिव्यक्ति है (15.1); नतीजा दूसरे के प्रकार का है और एक प्रवण है।
- दूसरे और तीसरे दोनों ऑपरेटरों में टाइप शून्य है; परिणाम शून्य शून्य का है और एक प्रवण है। [नोट: इसमें वह मामला शामिल है जहां दोनों ऑपरेंड फेंक-एक्सप्रेशन हैं। अंत टिप्पणी]

ऐसा प्रतीत होता है एक void करने के मूल्यांकन के रूप में है कि throw मायने रखता है, और यह अनुमति दी है।

+1

सी ++ 11 वीएस -2008 के लिए शायद ही प्रासंगिक है (सिवाय इसके कि यह एक सी ++ 11 नियम नहीं है, यह सी ++ 98 के बाद अपरिवर्तित है, जॉन का जवाब देखें)। –

+0

मेरे पास उद्धरण के लिए C++ 03 ड्राफ्ट (VS2008 के लिए) की एक प्रति नहीं है, या मैं इसके बजाय उद्धृत किया होगा। आप सही हैं कि यह आवश्यक रूप से वीएस -2008 पर लागू नहीं हुआ था। –

1

आंतरिक क्रैश को विजुअल स्टूडियो का एक बग माना जा सकता है। कोड संकलित होने के कारण एक कंपाइलर कभी क्रैश नहीं होना चाहिए।

इस त्रिगुट ऑपरेटर का एक बहुत ही अजीब उपयोग, एक सरल है अगर पहले वापसी के लिए एक बहुत बेहतर मुहावरा होगा: इस जा रहा है मान्य कोड की परवाह किए बिना या नहीं

if(m_something == 0) 
    throw std::logic_error("Something wrong happened"); 

return m_something; 
संबंधित मुद्दे