क्या C ++ 11 वेक्टर <const T> की अनुमति देता है?


82

कंटेनर आवश्यकताओं को C ++ 03 से C ++ 11 में बदल दिया है। जबकि C ++ 03 में कंबल की आवश्यकताएं थीं (जैसे कि वेक्टर के लिए प्रतिलिपि निर्माण और असाइनमेंट की प्रतिलिपि), C ++ 11 प्रत्येक कंटेनर ऑपरेशन (धारा 23.2) पर ठीक-ठीक आवश्यकताओं को परिभाषित करता है।

नतीजतन, आप एक प्रकार को स्टोर कर सकते हैं जो कॉपी-कंस्ट्रक्टेबल है, लेकिन असाइन करने योग्य नहीं है - जैसे कि एक कॉन्स्टेबल सदस्य के साथ एक संरचना - जब तक आप केवल कुछ ऑपरेशन करते हैं, जिसमें असाइनमेंट (निर्माण) की आवश्यकता नहीं होती है और push_backऐसे ऑपरेशन होते हैं ; insert) नहीं है।

मैं जो सोच रहा हूं वह है: क्या इसका मतलब यह है कि मानक अब अनुमति देता है vector<const T>? मुझे ऐसा कोई कारण नहीं दिख रहा है - यह नहीं होना चाहिए const T, जैसे कि एक कांस्टेबल सदस्य के साथ एक संरचना, एक प्रकार है जो रचनात्मक रूप से कॉपी है लेकिन असाइन करने योग्य नहीं है - लेकिन मुझे कुछ याद हो सकता है।

(क्या मुझे लगता है कि मुझे कुछ याद किया गया हो सकता है का हिस्सा है, यह है कि अगर आप तात्कालिकता करने की कोशिश करते हैं vector<const T>, तो जीसी ट्रंक दुर्घटनाग्रस्त हो जाता है और जलता है , लेकिन यह ठीक है vector<T>जहां टी का एक सदस्य है)।

जवाबों:


55

नहीं, मेरा मानना ​​है कि आवंटनकर्ता आवश्यकताओं का कहना है कि टी एक "गैर-कास्ट, गैर-संदर्भ ऑब्जेक्ट प्रकार" हो सकता है।

आप निरंतर वस्तुओं के वेक्टर के साथ बहुत कुछ नहीं कर पाएंगे। और ए const vector<T>लगभग वैसे भी होगा।


कई वर्षों बाद यह त्वरित और गंदा जवाब अभी भी टिप्पणियों और वोटों को आकर्षित करने वाला लगता है। हमेशा ऊपर नहीं। :-)

तो कुछ उचित संदर्भ जोड़ने के लिए:

C ++ 03 मानक के लिए, जो मेरे पास कागज पर है, खंड 31 में तालिका [lib.allocator.requirements] कहते हैं:

T, U any type

ऐसा नहीं है कि किसी भी प्रकार वास्तव में काम किया।

इसलिए, अगला मानक, C ++ 11, एक करीबी ड्राफ्ट में [आबंटक.आवेदन] और अब तालिका 27 में कहता है :

T, U, C any non-const, non-reference object type

जो मैं मूल रूप से स्मृति से ऊपर लिखा था के बेहद करीब है। यह भी सवाल है कि किस बारे में था।

हालाँकि, C ++ 14 में ( ड्राफ्ट N4296 ) तालिका 27 अब कहती है:

T, U, C any non-const object type

संभवतः क्योंकि एक संदर्भ शायद एक वस्तु प्रकार नहीं है?

और अब C ++ 17 में ( ड्राफ्ट N4659 ) यह तालिका 30 है जो कहती है:

T, U, C any cv-unqualified object type (6.9)

इसलिए न केवल constखारिज किया जाता है, बल्कि यह भी कहा जाता है volatile। शायद पुरानी खबर वैसे भी, और सिर्फ एक स्पष्टीकरण।


कृपया हावर्ड हिनेंट की पहली-हाथ की जानकारी भी देखें , जो वर्तमान में नीचे है।


43
नीचे पंक्ति: हमने कॉन्स्टेंट टी रखने के लिए कंटेनरों को डिज़ाइन नहीं किया। हालांकि मैंने इसे कुछ सोचा था। और हम वास्तव में दुर्घटना से ऐसा करने के करीब आ गए। मेरे ज्ञान का सबसे अच्छा करने के लिए, वर्तमान चिपके बिंदु addressडिफ़ॉल्ट आवंटनकर्ता में अतिभारित सदस्य कार्यों की जोड़ी है : जब टी कास्ट होता है, तो इन दो अधिभार में एक ही हस्ताक्षर होते हैं। इसे ठीक करने का एक आसान तरीका यह होगा कि std::allocator<const T>किसी एक अतिभार को विशेषज्ञ और हटा दिया जाए।
हावर्ड हिनानट

4
@ HighCommander4: मैं सकारात्मक नहीं हूं। Libc ++ पर मैं एक सहकारी आवंटनकर्ता के साथ एक वेक्टर (यहां तक ​​कि एक गैर-रिक्त एक) का निर्माण कर सकता हूं। मैं इसके साथ कुछ और नहीं कर सकता (नॉन-कास्ट)। मुझे यकीन नहीं है कि अगर "काम" की आपकी परिभाषा फिट बैठती है। मैं भी सकारात्मक नहीं हूँ अगर मैं अनजाने में एक विस्तार का लाभ ले रहा हूँ। यह सुनिश्चित करने के लिए, मुझे इस प्रश्न में और अधिक समय लगाने की आवश्यकता होगी। मैंने समय से पहले ऐसा निवेश किया है, लेकिन यह कई साल पहले था, और बहुत सारी चीजें अंतरिम में बदल गई हैं। यदि यह काम करता है, तो यह समिति की ओर से डिजाइन द्वारा नहीं है।
हॉवर्ड हेनतैन

1
@ हावर्ड: मैं ऐसा करने में सक्षम होने के लिए किसी भी तकनीकी बाधा के बारे में नहीं सोच सकता push_back। लेकिन अगर इसे डिजाइन की अनुमति नहीं है, तो हम इसे नहीं करने से बेहतर हैं। मैं बिलकुल उत्सुक था।
HighCommander4

8
एक कैश अक्सर अपरिवर्तनीय वस्तुओं का एक उत्परिवर्तित कंटेनर होता है, और एक सॉर्ट किया गया वेक्टर अक्सर मानचित्र के लिए एक विकल्प होता है, इसलिए मैं असहमत हूं कि कॉस्ट ऑब्जेक्ट का वेक्टर कम उपयोग का है।
क्रिस ओल्डवुड

9
यह शर्मनाक है। मैं std::vector<const T>बिल्कुल उपयोग कर रहा था क्योंकि यह बहुत समान है const std::vector<T>, लेकिन उस वर्ग के लिए बाद के नकारात्मक प्रभावों के बिना जो इसे धारण कर रहा है। वास्तव में, std::vector<const T>वास्तव में मुझे उन मामलों में सबसे ज्यादा जरूरत है, जहां मैं उपयोग करता हूं vector। अब मुझे छोड़ना होगा const- साथ ही यह विश्वसनीयता प्रदान करेगा।
वायलेट जिराफ

30

अपडेट करें

2011 में स्वीकृत (और सही) उत्तर के तहत मैंने टिप्पणी की:

नीचे पंक्ति: हम रखने के लिए कंटेनर डिजाइन नहीं किया था const T। हालांकि मैंने इसे कुछ सोचा था। और हम वास्तव में दुर्घटना से ऐसा करने के करीब आ गए। मेरे ज्ञान का सबसे अच्छा करने के लिए, वर्तमान चिपके बिंदु addressडिफ़ॉल्ट आवंटनकर्ता में अतिभारित सदस्य कार्यों की जोड़ी है : जब Tहै const, तो इन दो अधिभार में एक ही हस्ताक्षर है। इसे ठीक करने का एक आसान तरीका यह होगा कि std::allocator<const T>किसी एक अतिभार को विशेषज्ञ और हटा दिया जाए।

आगामी C ++ 17 ड्राफ्ट के साथ यह मुझे प्रतीत होता है कि हमने अब वैध vector<const T>कर दिया है, और मुझे विश्वास है कि हमने इसे गलती से किया है । :-)

P0174R0 को हटा addressसे भार के std::allocator<T>P0174R0std::allocator<const T> अपने औचित्य के हिस्से के रूप में समर्थन का कोई उल्लेख नहीं करता है ।

भूल सुधार

टीसी के नीचे की टिप्पणियों में सही ढंग से नोट किया गया है कि addressओवरलोड को हटा दिया गया है , हटाया नहीं गया है। मेरी गलती। पदावनत सदस्य २०.१०.९ में नहीं दिखाते हैं, जहां std::allocatorपरिभाषित किया गया है, लेकिन इसके बजाय धारा ९। जब मैंने यह पोस्ट किया तो मैंने इस संभावना के लिए अध्याय डी को स्कैन करने की उपेक्षा की।

धन्यवाद टीसी सुधार के लिए। मैंने इस भ्रामक उत्तर को हटाने पर विचार किया, लेकिन शायद इसे इस सुधार के साथ छोड़ देना सबसे अच्छा है ताकि शायद यह किसी और को उसी तरह से कल्पना को फैलाने से रोके जैसा मैंने किया।


7
यह बहुत मनोरंजक है! (अब हमें इसके बारे में वास्तव में शांत होने की आवश्यकता है, और इसे C ++ 17 में बिना किसी को देखे पर्ची देने दें :))
HighCommander4

क्या आवंटन आवश्यकताओं की तालिका अभी भी सिर्फ एकमुश्त प्रतिबंध नहीं लगाती है? भले ही, P0174R2 (जो संशोधन है में मतदान किया) केवल deprecates, निकल जाता है, नहीं address
टीसी

@TC: आप बिल्कुल सही कह रहे हैं। सुधारों के लिए धन्यवाद।
बजे हॉवर्ड हिनांत

तो c ++ 2x अंत में vector<const T>:)
MM

1
जवाब "नीचे पंक्ति: हमने कॉन्स्टेंट टी को पकड़ने के लिए कंटेनरों को डिज़ाइन नहीं किया।" मानता है कि लक्ष्य यह है कि कंटेनर को "कॉस्ट टी" रखना चाहिए। हालांकि, कोई यह तर्क दे सकता है कि उपयोगकर्ता का लक्ष्य कंटेनर पर परिचालन को प्रतिबंधित करना है - इसलिए कि 'बैक' () '' कॉन्स्टेंट टी एंड '' लौटाता है - चाहे कंटेनर में कोई भी हो।
हंस ओल्सन

8

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

तो यह काम नहीं करता है:

vector<const T> vec; 

सिर्फ समझने के लिए अन्य उत्तर क्यों पढ़ें। और, जैसा कि आप अनुमान लगा सकते हैं, यह काम नहीं करेगा:

vector<const shared_ptr<T>> vec;

Tअब नहीं है const, लेकिन एस vectorको पकड़े हुए है shared_ptr, Tएस नहीं ।

दूसरी ओर, यह काम करता है :

vector<const T *> vec;
vector<T const *> vec;  // the same as above

लेकिन इस मामले में, कास्ट को इंगित किया जा रहा ऑब्जेक्ट है, न कि खुद पॉइंटर (जो कि वेक्टर स्टोर है)। यह इसके बराबर होगा:

vector<shared_ptr<const T>> vec;

जो ठीक है।

लेकिन अगर हम constअभिव्यक्ति के अंत में रखते हैं, तो यह अब सूचक को एक में बदल देता है const, इसलिए निम्नलिखित संकलन नहीं करेगा:

vector<T * const> vec;

थोड़ा भ्रमित, मैं सहमत हूं, लेकिन आपको इसकी आदत है।


4

अन्य उत्तरों को लागू करने के लिए, एक और दृष्टिकोण का उपयोग करना है:

vector<unique_ptr<const T>> vec;

यदि यह ऐसा मामला है जहाँ आप यह लागू करना चाहते हैं कि केवल vecउसके सामान का स्वामित्व है। या यदि आप किसी वस्तु को गतिमान करना चाहते हैं vecऔर किसी समय उन्हें बाहर ले जाना चाहते हैं।

जैसा कि बताया गया है, पॉइंटर constशब्दार्थ भ्रमित हो सकता है, लेकिन shared_ptrऔर unique_ptrनहीं। const unique_ptr<T>एक unique_ptr<const T>कास्ट पॉइंटर है और एक कास्ट पॉइंटर है जैसा कि आप उम्मीद करेंगे।

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