2011-11-16 13 views
18

सी ++ 11 §27.5.4.2/21:`basic_ios :: swap` केवल आंशिक स्वैप क्यों करता है?

void swap(basic_ios& rhs);

प्रभाव:*this और rhs के राज्यों का आदान-प्रदान किया जाएगा, कि rdbuf() को छोड़कर यह रूप में एक ही मूल्य लौटा देगा फ़ंक्शन कॉल से पहले लौटाया गया, और rhs.rdbuf() फ़ंक्शन कॉल से पहले लौटाए गए वही मान वापस कर देगा।

क्या इस आंशिक अदला-बदली के लिए उपयोगी है?

क्या इससे परेशानी हो सकती है?

+0

अल्फ पी। स्टीनबाक एक प्रश्न पूछ रहे हैं। अविश्वसनीय। : | – Nawaz

+0

यह वास्तव में आश्चर्यजनक है। अगर मैं दो चीजों को स्वैप करता हूं तो मैं वास्तव में उन्हें स्वैप करने की उम्मीद करता हूं; अगर मुझे एक बग मिले और पाया कि यह 'rdbuf' को स्वैप नहीं कर रहा था, तो मुझे लगता है कि यह एक कार्यान्वयन बग था। – GManNickG

+0

वास्तव में आश्चर्यजनक आश्चर्यजनक। मैंने पहले फाइनल ड्राफ्ट की जांच की थी (एन 30 9 2) और यह वही है। मुझे आश्चर्य है कि यह सी ++ 03 में समान था, शायद एक विरासत अवशेष? –

उत्तर

20

आप मुझे इसके लिए दोषी ठहरा सकते हैं। समिति ने बदलने की कोशिश की है (मुझे लगता है कि दो बार), लेकिन हर बार समाधान टूटने चीजों को खत्म कर दिया।

स्वैप और सैमसंग को स्थानांतरित करने के एक दशक बाद हमारे आई/ओ सिस्टम पर फिर से लगाया गया था। और यह पूरी तरह से साफ फिट नहीं था।

ध्यान दें कि basic_ios::swap एक संरक्षित सदस्य फ़ंक्शन है और कोई नामस्थान-स्कोप संस्करण नहीं है। इस प्रकार इसे केवल व्युत्पन्न वर्ग (आमतौर पर आईट्रीम/ओस्ट्रीम) से बुलाया जा सकता है। ध्यान दें कि i/o_stream::swap भी संरक्षित है और कोई नामस्थान-स्कोप संस्करण नहीं है। और उनका स्पेस बेस क्लास swap पर कॉल करना है और फिर istream में gcount जैसे किसी स्थानीय डेटा को स्वैप करना है)।

अंततः string/filestream स्तर पर आप जो भी "सामान्य" swap पर विचार करेंगे: सार्वजनिक सदस्य और नामस्थान-स्कोप वेरिएंट। इस स्तर पर आपके पास डेटा सदस्य string/file buffer (rdbuf) और बेस क्लास है। इस स्तर पर swap बस आधार और डेटा सदस्यों को स्वैप करता है।

यह सब की उलझी विशेषता यह है कि आधार वर्ग में नीचे rdbuf() वास्तव में करने के लिए एक आत्म संदर्भित सूचक है व्युत्पन्न वर्ग के streambuf (basic_filebuf या basic_stringbuf) और है यही कारण है कि आप आधार वर्ग नहीं करना चाहते इन आत्म-संदर्भ बिंदुओं को स्वैप करने के लिए।

यह आधार swap अजीब बनाता है, लेकिन व्युत्पन्न ग्राहकों को छोड़कर हर कोई इसे सुरक्षित करता है। और व्युत्पन्न ग्राहक के swap के लिए कोड बाद में भ्रामक रूप से सरल दिख रहा है। और व्युत्पन्न स्तर पर, swap सार्वजनिक किया गया है और इस तरह व्यवहार करता है कि सार्वजनिक ग्राहक इसकी अपेक्षा करते हैं।

एक समान नृत्य कदम निर्माण के लिए बनाया जाता है और असाइनमेंट ले जाता है। ले जाएं निर्माण इस तथ्य से और जटिल है कि बेस क्लास वर्चुअल बेस है, और इस प्रकार इसके कन्स्ट्रक्टर को सबसे सीधे व्युत्पन्न वर्ग द्वारा नहीं कहा जाता है।

यह मजेदार था। यह अजीब लग रहा है। लेकिन यह अंततः काम करता है। ;-)

थोड़ा सा सुधार:

अल्बर्टो गणेश Barbati is responsiblei/ostream स्तर पर swap की रक्षा के लिए। यह उनके हिस्से पर एक बहुत अच्छी कॉल थी कि मैं अपने पहले डिजाइन के साथ पूरी तरह से चूक गया था।

+0

तो, tl; dr: बेस क्लास को पता नहीं है कि व्युत्पन्न वर्ग 'बफर को कैसे स्वैप करना है और यही कारण है कि यह व्युत्पन्न कक्षाओं को छोड़ देता है? 'Basic_streambuf' में वर्चुअल स्वैप फ़ंक्शन के बारे में क्या? – Xeo

+0

मैंने उस डिज़ाइन को प्रोटोटाइप नहीं किया है, लेकिन मुझे लगता है कि यह काम कर सकता है। व्युत्पन्न स्तर पर spec थोड़ा अजीब लग रहा है हालांकि: अपनी बेस क्लास स्वैप करें लेकिन आपके डेटा सदस्य नहीं। –

+0

सच है, ऐसा लगता है कि आधार या व्युत्पन्न विनिर्देश को iostreams के वर्तमान कार्यान्वयन के साथ अजीब दिखना है। एक साइड-नोट पर, क्या आपने कभी iostreams को फिर से डिजाइन करने या उन्हें पूरी तरह से किसी अन्य चीज़ के साथ बदलने के बारे में सोचा है? मैं देख सकता हूं कि यह पीछे की संगतता को बुरी तरह नुकसान पहुंचाएगा, लेकिन यह मानते हुए कि कोई समस्या नहीं होगी .. क्या समिति के माध्यम से विचार चल रहे विचार हैं, उदा। बूस्ट या एसएचएच में शामिल करने के लिए? – Xeo

2

मैं केवल एक सट्टा जवाब है ...

तो लेखक मान लिया है कि एक धारा एक आंतरिक बफर (उदाहरण के एक char buffer[50] डेटा सदस्य के लिए) का उपयोग कर सकते हैं, तो इस प्रावधान बफ़र्स की स्पष्ट रूप से सामग्री के रूप में आवश्यक है बदला जा सकता है, लेकिन उनका पता अपरिवर्तित रहेगा।

मुझे नहीं पता कि यह वास्तव में अनुमति है या नहीं।

+0

आप बफर को 'rdbuf' फ़ंक्शन के माध्यम से प्रतिस्थापित कर सकते हैं। –

+0

@ AlfP.Steinbach: हाँ, लेकिन मूल बफर कहां से आता है? इसे कहीं आवंटित करने के लिए बाध्य है, और मुझे इसके लिए एक आंतरिक सरणी का उपयोग करने से रोकने में कुछ भी नहीं मिला है। –

+1

बफर 'basic_streambuf ', या व्युत्पन्न प्रकार का एक वस्तु है। इसे 'stream.rdbuf (pMyNewBuffer)' के माध्यम से बदला जा सकता है। 'basic_ios' विनाशक को 'rdbuf()' ऑब्जेक्ट को नष्ट नहीं करने के रूप में दस्तावेज किया गया है, इसलिए उस ऑब्जेक्ट को प्रत्यक्ष सदस्य के रूप में रखना पूरी तरह से संभव है, लेकिन कक्षा को अभी भी 'rdbuf()' सूचक को बदलने का समर्थन करना है। –

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