क्या स्पष्ट रूप से एक चर घोषित किए बिना एक ही परिणाम प्राप्त करना संभव नहीं था auto
?
मैं आपके सवाल को थोड़ा इस तरह से बताने जा रहा हूँ जिससे आपको यह समझने में मदद मिलेगी कि आपको क्यों आवश्यकता है auto
:
क्या स्पष्ट रूप से एक प्रकार के प्लेसहोल्डर का उपयोग किए बिना एक ही परिणाम प्राप्त करना संभव नहीं था ?
क्या यह संभव नहीं था ? बेशक यह "संभव" था। सवाल यह है कि क्या यह करने के प्रयास के लायक होगा।
अन्य भाषाओं में अधिकांश वाक्यविन्यास जो टाइपनेम नहीं करते हैं, एक दो तरीकों से काम करते हैं। गो-लाइक तरीका है, जहां name := value;
एक चर घोषित किया जाता है। और पाइथन जैसा तरीका है, जहां पहले घोषित नहीं होने पर name = value;
एक नया चर name
घोषित करता है।
मान लेते हैं कि C ++ में सिंटैक्स लागू करने के साथ कोई वाक्यविन्यास मुद्दे नहीं हैं (भले ही मैं पहले ही देख सकता हूं कि C ++ में identifier
इसके बाद :
"लेबल बनाएं" का अर्थ है)। तो, आप प्लेसहोल्डर्स की तुलना में क्या खो देते हैं?
खैर, मैं अब ऐसा नहीं कर सकता:
auto &name = get<0>(some_tuple);
देखें, auto
हमेशा "मूल्य" का अर्थ है। यदि आप एक संदर्भ प्राप्त करना चाहते हैं, तो आपको स्पष्ट रूप से एक का उपयोग करने की आवश्यकता है &
। और यह सही ढंग से संकलित करने में विफल हो जाएगा यदि असाइनमेंट अभिव्यक्ति एक प्रचलन है। न तो असाइनमेंट-आधारित सिंटैक्स में संदर्भ और मूल्यों के बीच अंतर करने का एक तरीका है।
अब, आप ऐसे असाइनमेंट सिंटैक्स को संदर्भों को घटा सकते हैं यदि दिए गए मान का संदर्भ है। लेकिन इसका मतलब यह होगा कि आप ऐसा नहीं कर सकते:
auto name = get<0>(some_tuple);
टपल से यह कॉपी करता है, जिससे एक स्वतंत्र वस्तु बनती है some_tuple
। कभी-कभी, यही आप चाहते हैं। यह और भी उपयोगी है अगर आप टपल से आगे बढ़ना चाहते हैं auto name = get<0>(std::move(some_tuple));
।
ठीक है, इसलिए शायद हम इन सिंटैक्स को इस अंतर के लिए थोड़ा बढ़ा सकते हैं। शायद &name := value;
या &name = value;
एक संदर्भ की तरह कटौती का मतलब होगा auto&
।
अच्छी बात है। इस बारे में क्या:
decltype(auto) name = some_thing();
ओह ये सही हैं; सी ++ वास्तव में दो प्लेसहोल्डर हैं: auto
औरdecltype(auto)
। इस कटौती का मूल विचार यह है कि यह ठीक वैसे ही काम करता है जैसे आपने किया था decltype(expr) name = expr;
। तो हमारे मामले में, अगर some_thing()
कोई वस्तु है , तो वह एक वस्तु को घटा देगा। यदि some_thing()
एक संदर्भ है, तो यह एक संदर्भ काट देगा।
यह बहुत उपयोगी होता है जब आप टेम्पलेट कोड में काम कर रहे होते हैं और निश्चित रूप से निश्चित नहीं होते हैं कि किसी फ़ंक्शन का रिटर्न मान क्या होगा। यह अग्रेषण के लिए बहुत अच्छा है, और यह एक आवश्यक उपकरण है, भले ही इसका व्यापक रूप से उपयोग न किया जाए।
इसलिए अब हमें अपने सिंटैक्स में और अधिक जोड़ना होगा। name ::= value;
"क्या decltype(auto)
करता है" का अर्थ है। मेरे पास पाइथोनिक वैरिएंट के बराबर नहीं है।
इस वाक्यविन्यास को देखते हुए, क्या यह गलती से गलत प्रकार के लिए आसान नहीं है? इतना ही नहीं, यह शायद ही स्व-दस्तावेजीकरण है। यहां तक कि अगर आपने पहले कभी नहीं देखा है decltype(auto)
, तो यह बड़ा और स्पष्ट है कि आप कम से कम आसानी से बता सकते हैं कि कुछ खास चल रहा है। जबकि दृश्य अंतर ::=
और :=
न्यूनतम है।
लेकिन यह राय सामान है; अधिक ठोस मुद्दे हैं। देखें, यह सब असाइनमेंट सिंटैक्स का उपयोग करने पर आधारित है। अच्छा ... उन जगहों के बारे में जो आप असाइनमेंट सिंटैक्स का उपयोग नहीं कर सकते हैं ? ऐशे ही:
for(auto &x : container)
क्या हम इसे बदल सकते हैं for(&x := container)
? क्योंकि ऐसा लगता है कि रेंज-आधारित से बहुत अलग है for
। ऐसा लगता है कि यह एक नियमित for
लूप से इनिशलाइज़र स्टेटमेंट है , न कि रेंज-आधारित for
। यह गैर-कटौती वाले मामलों से एक अलग वाक्यविन्यास भी होगा।
साथ ही, प्रतिलिपि-आरंभीकरण (उपयोग करना =
) C ++ में प्रत्यक्ष-आरंभीकरण (निर्माण सिंटैक्स का उपयोग करके) के समान नहीं है। तो name := value;
उन मामलों में काम नहीं कर सकता है जहां auto name(value)
होगा।
निश्चित रूप से, आप घोषणा कर सकते हैं कि :=
प्रत्यक्ष-आरंभीकरण का उपयोग करेगा, लेकिन यह बाकी सी + + के व्यवहार के तरीके के साथ काफी अनुरूप होगा।
इसके अलावा, एक और बात है: C ++ 14। इसने हमें एक उपयोगी कटौती सुविधा प्रदान की: वापसी प्रकार की कटौती। लेकिन यह प्लेसहोल्डर्स पर आधारित है। रेंज-बेस्ड की तरह for
, यह मूल रूप से एक टाइपनेम पर आधारित होता है जो कंपाइलर द्वारा भरा जाता है, किसी विशेष नाम और अभिव्यक्ति के लिए लागू किए गए कुछ सिंटैक्स द्वारा नहीं।
देखें, ये सभी समस्याएं एक ही स्रोत से आती हैं: आप चर घोषित करने के लिए पूरी तरह से नए वाक्यविन्यास का आविष्कार कर रहे हैं। प्लेसहोल्डर-आधारित घोषणाओं को नए सिंटैक्स का आविष्कार नहीं करना पड़ा । वे पहले की तरह सटीक सिंटैक्स का उपयोग कर रहे हैं; वे सिर्फ एक नए कीवर्ड को नियोजित कर रहे हैं जो एक प्रकार की तरह कार्य करता है, लेकिन इसका एक विशेष अर्थ है। यह वही है जो इसे रेंज-आधारित for
और वापसी प्रकार की कटौती के लिए काम करने की अनुमति देता है । यह वह है जो इसे कई रूपों ( auto
बनाम decltype(auto)
) के लिए अनुमति देता है । इत्यादि।
प्लेसहोल्डर काम करते हैं क्योंकि वे समस्या का सबसे सरल समाधान हैं, साथ ही साथ वास्तविक प्रकार के नाम का उपयोग करने के सभी लाभों और सामान्यता को बनाए रखते हैं। यदि आप एक और विकल्प के साथ आए, जो सार्वभौमिक रूप से प्लेसहोल्डर्स के रूप में काम करता है, तो यह अत्यधिक संभावना नहीं है कि यह प्लेसहोल्डर्स के रूप में सरल होगा।
जब तक कि यह अलग-अलग कीवर्ड या प्रतीकों के साथ सिर्फ प्लेसहोल्डर्स नहीं था ...