2010-11-13 9 views
6

गैर-फेंकने वाले स्वैप मुहावरे को लागू करते समय, क्या मुझे throw() का उपयोग करना चाहिए?क्या मुझे गैर-फेंकने वाले स्वैप को लागू करते समय फेंक() का उपयोग करना चाहिए?

namespace A 
{ 
    struct B 
    { 
    void swap(B& other) throw() 
    { /* fancy stuff that doesn't throw */ } 
    }; 

    void swap(B& lhs, B& rhs) throw() 
    { lhs.swap(rhs); } 
} 

namespace std 
{ 
    template<> 
    void swap(A::B& lhs, A::B& rhs) throw() 
    { lhs.swap(rhs); } 
} 

विशेष रूप से मैं std::swap की विशेषज्ञता पर throw() विनिर्देश लगाने के बारे में चिंता।

बोनस प्रश्न:
क्या सी ++ 0x के noexcept कीवर्ड का उपयोग करते समय उत्तर अलग है?

+0

आप उन तीन स्वैप घोषणाओं को एक से नीचे सरल बना सकते हैं: 'संरचना बी {मित्र शून्य स्वैप (बीएंडए, बीएंड बी) {/ * ...* /}}; ', तो बस उपयोगकर्ताओं को swd :: swap का उपयोग करके स्वैप का उपयोग करने की आवश्यकता होती है; स्वैप (ए, बी); 'जो एडीएल के माध्यम से आपके स्वैप में खींचता है (या वे बूस्ट :: स्वैप का उपयोग कर सकते हैं, जो पहले से ही यह करता है)। विशेष रूप से, यह std :: स्वैप पर अपवाद विनिर्देश के बारे में चिंता को रोकता है, यदि आप अपने स्वैप के लिए एक का उपयोग करने का निर्णय लेते हैं। –

उत्तर

4

सी ++ 03 में आप इसे वहां डाल सकते हैं, लेकिन यदि यह सच है कि फैंसी सामान फेंक नहीं जाता है, तो यह मूल रूप से केवल दस्तावेज़ीकरण है। यह फ़ंक्शन पर कॉल के आसपास try/catch(...) { std::unexpected(); } के बराबर जोड़कर प्रदर्शन को प्रभावित कर सकता है या नहीं: यह कार्यान्वयन पर निर्भर करता है कि यह प्रदर्शन को प्रभावित किए बिना कर सकता है या नहीं।

आप C++ 0x में noexceptऑपरेटर (5.3.7) का उपयोग करने की योजना बना रहे, फिर अचानक यह गैर फेंक अपवाद विनिर्देशों होने लायक हो जाता है, तो यह है कि ऑपरेटर "सही" जवाब देता है। मुझे वास्तव में पता नहीं है कि noexcept ऑपरेटर क्या है, लेकिन यदि इसके लिए एक चालाक सामान्य उपयोग है, उदाहरण के लिए एल्गोरिदम जो कुछ गैर-फेंकने पर अधिक कुशल बन जाते हैं, तो मुझे लगता है कि यह कार्यों को चिह्नित करने के लिए आवश्यक हो जाएगा जो कुछ भी लाभ प्राप्त करने के लिए, बढ़ रहा है।

उदाहरण के लिए:

void foo() noexcept; 
void bar(); 

template <void(*FUNC)()> 
void generic_thing() { 
    if (noexcept(FUNC()) { 
     // this won't throw, perhaps we can somehow take advantage of that 
     FUNC(); 
    } else { 
     // this might throw 
     FUNC(); 
    } 
} 

पुरानी शैली अपवाद विनिर्देशों (गतिशील-अपवाद-विनिर्देश) (और सी ++ 03 में व्यर्थ) C++ 0x में पदावनत कर रहे हैं।

+0

'noexcept' ऑपरेटर को अभिव्यक्ति की आवश्यकता नहीं है। यानी 'noexcept == noexcept (सत्य) '। एफसीडी में §15.4-1 देखें। –

+1

@caspin: 'noexcept' * ऑपरेटर * करता है। यह एक यूनरी ऑपरेटर है जिसे 5.3.7 में परिभाषित किया गया है, और यह परीक्षण करता है कि इसका मूल्यांकन किए बिना अभिव्यक्ति * फेंक सकता है या नहीं। सहमत हैं कि * अपवाद-विनिर्देश * में उपयोग किए गए अपवाद * कीवर्ड *, को अभिव्यक्ति की आवश्यकता नहीं है। यकीन नहीं है कि मैंने वहां 'सत्य' क्यों रखा है। –

+0

क्या 'नोएक्ससेप्ट' ऑपरेटर 'बूल कॉन्टेक्सप्र' देता है? मैं कहूंगा कि यह निश्चित रूप से संभव है और इस प्रकार इसे टेम्पलेट पैरामीटर के रूप में उपयोग करना संभव होना चाहिए ... हालांकि मुझे संदेह है कि इसके नमक के किसी भी कंपाइलर मृत शाखा को खत्म कर देगा और यदि परिणाम गणना योग्य है तो 'if' पूरी तरह से हटा दें संकलन समय पर ... और यह क्यों नहीं होना चाहिए? –

1

यथार्थवादी, नहीं। अपवाद विनिर्देश एक सुंदर विचार थे, लेकिन उनकी वास्तविकता यह थी कि उन्होंने बहुमत कोड की मदद से अधिक बाधा डाली। कोई भी उनका उपयोग नहीं करता है और उन्हें सी ++ 0x में बहिष्कृत किया जाता है। आधुनिक सी ++ में अपवाद विनिर्देश लिखने में समय व्यतीत न करें।

+1

मुझे पता है कि अपवाद विनिर्देश एक बुरा विचार है और बहिष्कृत है। मैंने सोचा कि 'फेंक() '(खाली विनिर्देश) नियम के अपवाद था। मैंने सोचा था कि 'नोएक्ससेप्ट' 'फेंक()' का एक अद्यतन संस्करण था जो 'फेंक()' को संकलित समय अभिव्यक्ति के माध्यम से चालू और बंद करने की क्षमता के साथ था। –

3

यह एक अच्छा विचार नहीं है, नहीं। कारण यह है कि मानक जानता है कि कभी-कभी throw() शुद्धता को लागू करना असंभव है, जो throw() को पहले स्थान पर लाया गया था। विशेष रूप से, टेम्पलेट्स के मामले में जहां तत्काल के आधार पर एक अपवाद फेंक दिया जा सकता है या नहीं, टेम्पलेट तत्कालता के बिना शुद्धता की जांच करना असंभव है। मानक इसलिए अपवाद विनिर्देशक को लागू करने के लिए कंपाइलरों की आवश्यकता नहीं है; वास्तव में, यह को अभिव्यक्ति को अस्वीकार करने से एक कार्यान्वयन को रोकता है "केवल इसलिए कि जब इसे निष्पादित किया जाता है तो यह फेंक देता है या एक अपवाद फेंक सकता है कि युक्त फ़ंक्शन अनुमति नहीं देता है" (15.4/11)।

यदि throw() का दस्तावेज़ीकरण के अलावा कोई प्रभाव नहीं है तो इसे टिप्पणी की जानी चाहिए; इस तरह कम से कम यह मानव पर्यवेक्षक को गुमराह करने का जोखिम नहीं उठाता है।

noexcept के साथ मामला पूरी तरह से अलग है। noexcept एक अलग कारण के लिए आता है; प्रदर्शन की है। यदि आप संकलक की गारंटी दे सकते हैं तो कोई अपवाद नहीं फेंक दिया गया है तो संकलक स्वयं को कुछ अनुकूलन करने की अनुमति देता है। लेकिन आप को खुद को चेक करना होगा। इसलिए, यदि वास्तव में swap() फेंक नहीं देता है (और यह नहीं होना चाहिए; यह उसका राजन डी'एटर है) तो noexcept निर्दिष्ट करना एक अच्छा विचार है।

+0

"मानक इसलिए अपवाद विनिर्देशक को लागू करने के लिए कंपाइलरों की आवश्यकता नहीं है।" - इससे अधिक, मानक के लिए आवश्यक है कि कंपाइलर्स * अपवाद विनिर्देशों को लागू न करें (15.4/10)। –

+0

@SteveJessop सही, मुझे सही करने के लिए धन्यवाद। यह 15.4/11 है, वैसे भी। – wilhelmtell

+0

@ विल्हेल्म: एक सुधार के रूप में नहीं था, बस अतिरिक्त जानकारी :-)। मेरा नंबरिंग आईएसओ/आईईसी 14882: 2003 (ई) ', यानी सी ++ 03 से है। जैसा कि आप कहते हैं, यह C++ 0x FCD में 15.4/11 है। –

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

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