क्यों नहीं std :: initializer_list एक भाषा में बनाया गया?


95

std::initializer_listएक कोर-भाषा अंतर्निहित क्यों नहीं है?

यह मुझे लगता है कि यह C ++ 11 की एक महत्वपूर्ण विशेषता है और अभी तक इसका अपना आरक्षित कीवर्ड (या कुछ समान) नहीं है।

इसके बजाय, initializer_listयह मानक लाइब्रेरी से सिर्फ एक टेम्प्लेट क्लास है जिसमें कंपाइलर द्वारा संभाला गया नया ब्रेड-इन-इन-लिस्ट सिंटैक्स से एक विशेष, अंतर्निहित मैपिंग है । {...}

पहले सोचा, यह समाधान काफी हैक है

क्या इस तरह C ++ भाषा में नए जोड़ अब लागू किए जाएंगे: कुछ टेम्प्लेट कक्षाओं की अंतर्निहित भूमिकाओं द्वारा और कोर भाषा द्वारा नहीं ?


कृपया इन उदाहरणों पर विचार करें:

   widget<int> w = {1,2,3}; //this is how we want to use a class

नया वर्ग क्यों चुना गया:

   widget( std::initializer_list<T> init )

इन विचारों में से किसी एक के समान उपयोग करने के बजाय :

   widget( T[] init, int length )  // (1)
   widget( T... init )             // (2)
   widget( std::vector<T> init )   // (3)
  1. एक क्लासिक सरणी, आप शायद constयहाँ और वहाँ जोड़ सकते हैं
  2. तीन डॉट्स पहले से ही भाषा में मौजूद हैं (var-args, अब varadic टेम्प्लेट), सिंटैक्स का फिर से उपयोग क्यों नहीं करें (और इसे अंतर्निहित महसूस करें )
  3. बस एक मौजूदा कंटेनर, जोड़ सकता है constऔर&

वे सभी पहले से ही भाषा का एक हिस्सा हैं। मैंने केवल अपने 3 पहले विचारों को लिखा है, मुझे यकीन है कि कई अन्य दृष्टिकोण हैं।


26
मानक समिति नए कीवर्ड जोड़ने से नफरत करती है !
एलेक्स चेम्बरलेन

11
यह मैं समझता हूं, लेकिन भाषा का विस्तार करने के लिए कई संभावनाएं हैं ( कीवर्ड सिर्फ एक उदाहरण था )
emesx

10
std::array<T>से अधिक 'भाषा का हिस्सा' नहीं है std::initializer_list<T>। और ये लगभग केवल पुस्तकालय घटक नहीं हैं जो भाषा पर निर्भर करते हैं। देखें , new/ delete, type_infoविभिन्न अपवाद प्रकार size_t, आदि
bames53

6
@ ईलम्स: मैंने सुझाव दिया होगा const T(*)[N], क्योंकि यह बहुत ही समान व्यवहार करता है कि कैसे std::initializer_listकाम करता है।
मूइंग डक

1
यह उत्तर देता है कि क्यों std::arrayया एक सांख्यिकीय-आकार की सरणी कम वांछनीय विकल्प हैं।
बॉयसी

जवाबों:


48

"कोर" भाषा सुविधाओं के पहले से ही उदाहरण थे जो stdनाम स्थान में परिभाषित प्रकार लौटे थे । typeidरिटर्न std::type_infoऔर एक बिंदु (शायद एक बिंदु खींच) sizeofरिटर्न std::size_t

पूर्व मामले में, आपको पहले से ही इस तथाकथित "कोर भाषा" सुविधा का उपयोग करने के लिए एक मानक हेडर शामिल करने की आवश्यकता है।

अब, शुरुआती सूचियों के लिए ऐसा होता है कि ऑब्जेक्ट को उत्पन्न करने के लिए किसी कीवर्ड की आवश्यकता नहीं होती है, वाक्यविन्यास संदर्भ-संवेदनशील घुंघराले ब्रेसिज़ होता है। इसके अलावा यह जैसा है वैसा ही है type_info। व्यक्तिगत रूप से मुझे नहीं लगता कि किसी कीवर्ड की अनुपस्थिति उसे "अधिक हैसी" बनाती है। थोड़ा और अधिक आश्चर्यजनक, शायद, लेकिन याद रखें कि उद्देश्य वही ब्रेड-इनिशियलाइज़र सिंटैक्स की अनुमति देना था जो पहले से ही समुच्चय के लिए अनुमति दी गई थी।

तो हां, आप भविष्य में इस डिजाइन सिद्धांत के बारे में अधिक उम्मीद कर सकते हैं:

  • यदि अधिक अवसर उत्पन्न होते हैं, जहां नए कीवर्ड के बिना नई सुविधाओं को पेश करना संभव है, तो समिति उन्हें ले जाएगी।
  • यदि नई सुविधाओं के लिए जटिल प्रकारों की आवश्यकता होती है, तो उन प्रकारों stdको बिलिंस के बजाय रखा जाएगा ।

अत:

  • यदि किसी नई सुविधा के लिए एक जटिल प्रकार की आवश्यकता होती है और उसे नए कीवर्ड के बिना पेश किया जा सकता है, तो आपको वही मिलेगा जो आपके यहां है, जो "कोर भाषा" है, जिसमें कोई नए कीवर्ड नहीं हैं और जो लाइब्रेरी प्रकारों का उपयोग करता है std

मुझे लगता है कि यह नीचे आता है, यह है कि "मुख्य भाषा" और मानक पुस्तकालयों के बीच सी ++ में कोई पूर्ण विभाजन नहीं है। वे मानक में अलग-अलग अध्याय हैं, लेकिन प्रत्येक दूसरे को संदर्भित करता है, और यह हमेशा ऐसा रहा है।

सी ++ 11 में एक और दृष्टिकोण है, जो यह है कि लैम्ब्डा उन वस्तुओं को पेश करता है जिनके पास संकलक द्वारा उत्पन्न गुमनाम प्रकार होते हैं। क्योंकि उनका कोई नाम नहीं है, वे किसी नाम स्थान पर नहीं हैं, निश्चित रूप से नहीं std। यह शुरुआती सूचियों के लिए एक उपयुक्त दृष्टिकोण नहीं है, हालांकि, क्योंकि आप उस प्रकार का उपयोग करते हैं जब आप उस निर्माता को लिखते हैं जो एक को स्वीकार करता है।


1
मुझे ऐसा लगता है कि इस प्रकार की अंतर्निहित भूमिकाओं के कारण यह विभाजन संभव नहीं है । type_infoऔर size_tअच्छी दलीलें हैं .. अच्छी तरह size_tसे सिर्फ एक टाइप्डफ है .. तो चलो इसे छोड़ दें। के बीच का अंतर type_infoऔर initializer_listहै कि पहले एक का परिणाम है है स्पष्ट ऑपरेटर, और एक के दूसरे निहित संकलक कार्रवाई। यह भी मुझे लगता है, कि कुछ पहले से मौजूद कंटेनरों से बदला जा initializer_list सकता है .. या फिर अभी तक बेहतर है: कोई भी उपयोगकर्ता तर्क प्रकार की घोषणा करता है!
इमेक्स

4
... या यह सरल कारण हो सकता है कि यदि आपने इसके लिए एक कंस्ट्रक्टर लिखा vectorहै, arrayतो आप सही प्रकार के किसी भी सरणी से एक वेक्टर का निर्माण कर सकते हैं , न कि इनिशियलाइज़र सूची सिंटैक्स द्वारा उत्पन्न। मुझे यकीन नहीं है कि किसी भी कंटेनर से निर्माण करना एक बुरी बात होगी array, लेकिन नए सिंटेक्स को पेश करने में समिति का इरादा नहीं है।
स्टीव जेसप

2
@ क्रिसियन: नहीं, std::arrayकिसी भी निर्माता के पास नहीं है। std::arrayमामले बस कुल-प्रारंभ है। इसके अलावा, मैं आपको लाउंज <C ++> चैट रूम में शामिल होने के लिए स्वागत करता हूं, क्योंकि यह चर्चा थोड़ी लंबी हो रही है।
Xio

3
@ChristianRau: Xio का अर्थ है कि जब एलिमिनेटर सूची का निर्माण किया जाता है तो तत्वों की नकल की जाती है। एक प्रारंभिक सूची की नकल करना निहित तत्वों की नकल नहीं करता है।
मूइंग डक

2
@ क्रिश्चियन सूची-आरंभीकरण initializer_list का मतलब नहीं है। यह कई चीजें हो सकती हैं, जिनमें अच्छा ओले प्रत्यक्ष-आरंभीकरण, या समग्र प्रारंभिककरण शामिल है। उनमें से कोई भी initializer_list शामिल नहीं है (और कुछ इस तरह से काम नहीं कर सकते हैं )।
आर। मार्टिनो फर्नांडिस

42

लगता है कि C ++ मानक समिति नए खोजशब्दों को नहीं जोड़ना पसंद करती है, शायद इसलिए कि मौजूदा कोड को तोड़ने का खतरा बढ़ जाता है (विरासत कोड उस कीवर्ड को एक चर, एक वर्ग, या जो भी हो) के नाम के रूप में उपयोग कर सकता है।

इसके अलावा, यह मुझे लगता है कि टेम्पर्ड std::initializer_listकंटेनर के रूप में परिभाषित करना एक बहुत ही सुंदर विकल्प है: यदि यह एक कीवर्ड था, तो आप इसके अंतर्निहित प्रकार को कैसे एक्सेस करेंगे? आप इसके माध्यम से कैसे पुनरावृति करेंगे? आपको नए ऑपरेटरों के एक समूह की भी आवश्यकता होगी, और यह आपको अधिक नाम और अधिक कीवर्ड याद रखने के लिए मजबूर करेगा, वही चीजें जो आप मानक कंटेनरों के साथ कर सकते हैं।

std::initializer_listकिसी भी अन्य कंटेनर के रूप में व्यवहार करने से आपको सामान्य कोड लिखने का अवसर मिलता है जो उन चीजों में से किसी के साथ काम करता है।

अपडेट करें:

फिर मौजूदा के कुछ संयोजन का उपयोग करने के बजाय एक नया प्रकार क्यों पेश करें? (टिप्पणियों से)

शुरू करने के लिए, अन्य सभी कंटेनरों में तत्वों को जोड़ने, हटाने और अनुकरण करने के तरीके हैं, जो संकलक-जनित संग्रह के लिए वांछनीय नहीं हैं। एकमात्र अपवाद है std::array<>, जो एक निश्चित आकार के सी-स्टाइल सरणी को लपेटता है और इसलिए केवल उचित उम्मीदवार रहेगा।

हालांकि, निकोल बोलस के रूप में सही ढंग से टिप्पणी में बताते हैं, के बीच एक और, मौलिक अंतर std::initializer_listऔर अन्य सभी मानक कंटेनर (सहित std::array<>) है कि बाद वाले है मूल्य अर्थ विज्ञान , जबकि std::initializer_listहै संदर्भ अर्थ विज्ञान । एक प्रतिलिपि बनाई जा रही std::initializer_list, उदाहरण के लिए, तत्व उसमें शामिल की एक प्रति का कारण नहीं बनेगा।

इसके अलावा (एक बार फिर, निकोल बोलस के सौजन्य से), ब्रेस-इनिशियलाइज़ेशन सूचियों के लिए एक विशेष कंटेनर होने से उपयोगकर्ता को इनिशियलाइज़ेशन करने के तरीके पर ओवरलोडिंग की अनुमति मिलती है।


4
फिर मौजूदा के कुछ संयोजन का उपयोग करने के बजाय एक नया प्रकार क्यों पेश करें?
इमेक्स

3
@ लाइम: वास्तव में यह अधिक पसंद है std::array। लेकिन संकलन-समय सरणी लपेटते std::arrayसमय मेमोरी आवंटित करता है std::initializaer_list। के बीच अंतर के रूप में समझें char s[] = "array";और char *s = "initializer_list";
रॉडरिगो

2
और यह एक सामान्य प्रकार होने के कारण ओवरलोडिंग, टेम्प्लेट विशेषज्ञता, नाम-सजावट और इसी तरह, गैर-मुद्दे बनाता है।
रॉडरिगो

2
@rodrigo: std::arrayकिसी भी स्मृति को आवंटित नहीं करता है, यह एक सादा है T arr[N];, वही चीज जो समर्थन कर रही है std::initializer_list
Xeo

6
@ Xeo: मेमोरी T arr[N] आवंटित करता है , शायद डायनेमिक हीप में नहीं बल्कि कहीं और ... तो करता है std::array। हालांकि initializer_listउपयोगकर्ता द्वारा एक गैर-खाली का निर्माण नहीं किया जा सकता है, इसलिए यह स्पष्ट रूप से मेमोरी आवंटित नहीं कर सकता है।
रॉडरिगो

6

यह कोई नई बात नहीं है। उदाहरण के लिए, वर्ग में विशिष्ट तरीकों या स्वसंपूर्ण कार्यों के अस्तित्वfor (i : some_container) पर निर्भर करता है । C # यहां तक ​​कि इसके .NET पुस्तकालयों पर भी अधिक निर्भर करता है। वास्तव में, मुझे लगता है, कि यह काफी सुरुचिपूर्ण समाधान है, क्योंकि आप अपनी कक्षाओं को भाषा विनिर्देश को जटिल किए बिना कुछ भाषा संरचनाओं के साथ संगत बना सकते हैं।some_container


2
कक्षा या स्टैंड-अलोन की विधियाँ beginऔर endविधियाँ। यह थोड़ा अलग IMO है।
इमेक्स

3
क्या यह? फिर से आपके पास अपने कोड के विशिष्ट निर्माण पर निर्भर एक शुद्ध भाषा निर्माण है। उदाहरण के लिए, नए कीवर्ड की शुरुआत करते हुए यह भी किया जा सकता है,iterable class MyClass { };
Spook

लेकिन आप जहां चाहें तरीके रख सकते हैं, उन्हें लागू कर सकते हैं, हालांकि आप चाहते हैं .. कुछ समानता है, मैं सहमत हूं! यह सवाल initializer_listहालांकि है
emesx

4

यह वास्तव में कोई नई बात नहीं है और कितने लोगों ने बताया है, यह अभ्यास C ++ में था और सी # में है।

आंद्रेई अलेक्जेंड्रेस्कु ने इस बारे में एक अच्छी बात का उल्लेख किया है: आप इसे काल्पनिक "कोर" नामस्थान के हिस्से के रूप में सोच सकते हैं, फिर यह अधिक समझ में आएगा।

: तो, यह वास्तव में की तरह कुछ है core::initializer_list, core::size_t, core::begin(), core::end()और पर इतना। यह सिर्फ एक दुर्भाग्यपूर्ण संयोग है कि stdनेमस्पेस में इसके अंदर कुछ मुख्य भाषा के निर्माण हैं।


2

यही नहीं यह पूरी तरह से मानक पुस्तकालय में काम कर सकता है। मानक लाइब्रेरी में शामिल होने का मतलब यह नहीं है कि कंपाइलर चालाक चाल नहीं खेल सकता है।

हालांकि यह सभी मामलों में सक्षम नहीं हो सकता है, यह बहुत अच्छी तरह से कह सकता है: यह प्रकार अच्छी तरह से जाना जाता है, या एक साधारण प्रकार, को अनदेखा करता है initializer_listऔर बस एक स्मृति छवि है कि प्रारंभिक मूल्य क्या होना चाहिए।

दूसरे शब्दों में या के int i {5};बराबर हो सकता है या यहां तक ​​कि जहां एक साधारण रैपर वर्ग में एक इंटिव पर एक तुच्छ कंस्ट्रक्टर होता हैint i(5);int i=5;intwrapper iw {5};intwrapperinitializer_list


क्या हमारे पास वास्तव में इस तरह "चालाक चाल" खेलने वाले संकलकों के प्रजनन योग्य उदाहरण हैं? यह थोड़े -से के तहत तर्क के लिए खड़ा है , लेकिन मैं पुष्टि देखना चाहता हूं।
अंडरस्कोर_ड

कंपाइलरों के अनुकूलन का विचार यह है कि कंपाइलर कोड को किसी भी समकक्ष कोड में बदल सकता है। सी ++ विशेष रूप से "मुक्त" सार के लिए अनुकूलन पर निर्भर करता है। मानक पुस्तकालय से कोड को बदलने का विचार आम है (जीईसी बिलिन सूची में देखें) जीईसी बिलिन gcc.gnu.org/oniltocs/gcc/Other-Builtins.html पर देखें )।
पॉल डे व्रीज़

वास्तव में, आपका विचार int i {5}जिसमें कोई भी शामिल हैstd::initializer_list है गलत है। intकोई निर्माण करने वाला नहीं है std::initializer_list, इसलिए 5इसका निर्माण करने के लिए सीधे उपयोग किया जाता है। तो मुख्य उदाहरण अप्रासंगिक है; बस कोई अनुकूलन नहीं किया जाना है। इसके अलावा, चूंकि std::initializer_listकंपाइलर में 'काल्पनिक' एरे को बनाना और सम्‍मिलित करना शामिल है, मुझे लगता है कि यह अनुकूलन का पक्ष ले सकता है, लेकिन कंपाइलर में 'मैजिक' भाग है, इसलिए यह अलग है कि सामान्य रूप से ऑप्टिमाइज़र सुंदर के साथ कुछ भी कर सकता है या नहीं। सुस्त वस्तुएं जिसमें 2 पुनरावृत्तियाँ होती हैं, जिसके परिणामस्वरुप
अंडरस्कोर_ड

1

यह मुख्य भाषा का हिस्सा नहीं है क्योंकि इसे पूरी तरह से पुस्तकालय में लागू किया जा सकता है, बस लाइन operator newऔर operator delete। इसमें बनाने के लिए कंपाइलरों को और अधिक जटिल बनाने में क्या फायदा होगा?

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