2015-10-02 7 views
11

एरिक निबेलर के range proposal,
पढ़ने के दौरान मैं अंतराल के लिए प्रतिस्थापन के रूप में सेंटीनेल शब्द भर गया हूं।
मुझे अंतराल इटरेटर पर सेंटीनेल के लाभों को समझने में मुश्किल हो रही है।
क्या कोई व्यक्ति स्पष्ट रूप से तालिका में लाए जाने वाले स्पष्ट उदाहरण प्रदान कर सकता है जिसे मानक इटरेटर जोड़े के साथ नहीं किया जा सकता है?सेंटीनेल और एंड इटरेटर के बीच क्या अंतर है?

"एक प्रहरी एक पास्ट अंत इटरेटर का एक अमूर्त है। प्रहरी नियमित प्रकार है कि एक सीमा के अंत को निरूपित करने के लिए इस्तेमाल किया जा सकता है एक प्रहरी और पुनरावर्तक करेगा एक सीमा को दर्शाते हैं। समानता समेकित। एक सेंटीनेल एक तत्व को इंगित करता है जब एक इटरेटर मैं सेंटीनेल के बराबर तुलना करता हूं, और मैं उस तत्व को इंगित करता हूं। " - N4382

मुझे लगता है कि सेंटीनेल केवल स्थिति की बजाय सीमा के अंत को निर्धारित करने में कार्य के रूप में कार्य करते हैं?

उत्तर

10

सेंटीनेल बस एंडरेटर को एक अलग प्रकार की अनुमति देता है।

पिछले-एंड-एंड इटरेटर पर अनुमत संचालन सीमित हैं, लेकिन यह इसके प्रकार में दिखाई नहीं देता है। *.end() इटरेटर के लिए ठीक नहीं है, लेकिन संकलक आपको चलेगा।

एक सेंटीनेल में अन्य चीजों के साथ, असीमित अव्यवस्था, या ++ नहीं है। यह आम तौर पर कमजोर इटरेटर के रूप में प्रतिबंधित होता है जो अंत में इटेटरेटर से पहले होता है, लेकिन संकलन समय पर लागू होता है।

एक भुगतान है। अक्सर अंत राज्य का पता लगाने से यह आसान है। एक सेंटीनेल के साथ, == रन टाइम के बजाए संकलन समय पर "अन्य तर्क का अंत समाप्त हो गया है" को प्रेषित कर सकता है।

परिणाम यह है कि कुछ कोड जो सी समकक्ष से धीमे होते थे अब सी स्तर की गति तक संकलित होते हैं, जैसे std::copy का उपयोग करके एक शून्य समाप्त स्ट्रिंग की प्रतिलिपि बनाना। सेंटीनेल के बिना, आपको या तो प्रतिलिपि से पहले अंत खोजने के लिए स्कैन करना था, या बूल फ्लैग के साथ इटरेटर में पास करना था, "मैं अंत प्रेषित हूं" (या समकक्ष), और इसे == पर जांचें।

गिनती आधारित श्रेणियों के साथ काम करते समय अन्य समान फायदे हैं।इसके अलावा, ज़िप की कुछ चीजें व्यक्त करने के लिए आसान हो जाती हैं (अंत ज़िप प्रेषण दोनों स्रोत सेंटीनेल धारण कर सकता है, और अगर सेंटीनेल करता है तो बराबर लौटाएं: ज़िप इटरेटर्स या तो पहले इटरेटर की तुलना करें, या दोनों की तुलना करें)।

इसके बारे में सोचने का एक और तरीका यह है कि एल्गोरिदम पिछले एंडरेटर के रूप में पारित पैरामीटर पर इटरेटर अवधारणा की पूर्ण समृद्धि का उपयोग नहीं करते हैं, और यह कि इटरेटर को अभ्यास में अलग-अलग तरीके से संभाला जाता है। सेंटीनेल का मतलब है कि कॉलर उस तथ्य का फायदा उठा सकता है, जो बदले में संकलक इसे आसान बनाता है।


लिए पिन रेंज जब आप 2 या अधिक पर्वतमाला के साथ शुरू आप क्या मिलता है, और "ज़िप" उन्हें एक साथ एक ज़िपर की तरह है। सीमा अब व्यक्तिगत रेंज तत्वों के tuples से अधिक है। एक ज़िप पुनरावर्तक को आगे बढ़ाने से प्रत्येक "निहित" इटरेटर, और dereferencing और तुलना करने के लिए ditto आगे बढ़ता है।

+0

एक ज़िप रेंज क्या है? – Walter

+0

@walter ने फुटनोट – Yakk

+0

हम्म जोड़ा। लेकिन एक ज़िप इटरेटर एक रैंडमएक्सइटरेटर नहीं हो सकता है, क्योंकि इसके 'संदर्भ'' value_type 'के समान नहीं हैं। इसलिए कुछ मानक एल्गोरिदम काम नहीं कर सकता (जैसा आपने कहा है [स्वयं] (http://stackoverflow.com/a/32871002/1023390))। तो यह अच्छा क्या है? – Walter

2

सेंटीनेल और एंड इटरेटर्स समान हैं कि वे एक सीमा के अंत को चिह्नित करते हैं। वे अलग-अलग कैसे पता लगाते हैं में भिन्न होते हैं; या तो आप इसे इटेटरेटर का परीक्षण कर रहे हैं, या आप इटरेटर पर डेटा वैल्यू का परीक्षण कर रहे हैं। यदि आप पहले से ही डेटा पर परीक्षण कर रहे हैं, तो एक सेंटीनेल आपके एल्गोरिदम को बिना किसी अतिरिक्त परीक्षण के "मुफ्त में" समाप्त करने की अनुमति दे सकता है। यह या तो कोड को सरल बना सकता है, या इसे तेज़ी से बना सकता है।

एक बहुत ही सामान्य सेंटीनेल शून्य बाइट है जिसका प्रयोग स्ट्रिंग के अंत को चिह्नित करने के लिए किया जाता है। स्ट्रिंग के अंत के लिए एक अलग इटरेटर रखने की कोई आवश्यकता नहीं है, यह निर्धारित किया जा सकता है क्योंकि आप स्ट्रिंग के पात्रों के साथ काम करते हैं। इस सम्मेलन का नकारात्मक पक्ष यह है कि एक स्ट्रिंग में शून्य वर्ण नहीं हो सकता है।

ध्यान दें कि मैंने लिंक में प्रस्ताव पढ़ने से पहले यह जवाब लिखा था; यह एक सेंटीनेल की क्लासिक परिभाषा है जो प्रस्तावित परिभाषा से सहमत नहीं हो सकती है।

+2

जब आप कोड लिख रहे हैं तो वे भी उपयोगी होते हैं कि पायथन में जनरेटर के रूप में जाना जाएगा। अंत बिंदु ज्ञात नहीं है और संभवतः ज्ञात नहीं किया जा सकता है (उदाहरण के लिए एक ['istream_iterator'] (http://www.cplusplus.com/reference/iterator/istream_iterator/) सॉकेट या पाइप को लपेटना, जहां आपने ' टी पता है कि क्या आप दूसरे अंत तक अपने लेखन संभाल को बंद कर देते हैं। सेंटीनेल एक परिदृश्य निर्भर और पूर्ण परिभाषा के बजाय "पूर्ण होने" की तार्किक स्थिति का वर्णन करता है (उदाहरण के लिए जब पूर्णकर्ता 'vector.begin() ' + 'vector.size()') – ShadowRanger

0

एक सेंटीनेल शुरू करने के लिए केंद्रीय प्रेरणा यह है कि बहुत सारे इटरेटर ऑपरेशंस हैं जो समर्थित हैं लेकिन आमतौर पर एंड-इटरेटर end() के लिए कभी भी आवश्यकता नहीं होती है। उदाहरण के लिए, के माध्यम से इसे बढ़ाने में *end() के माध्यम से इसे संदर्भित करने में शायद ही कोई बिंदु नहीं है, और इसलिए (*) पर।

इसके विपरीत, end() का मुख्य उपयोग केवल क्रम में एक इटरेटर it के साथ तुलना करना signalize के लिए कि क्या it बात यह सिर्फ दोहराता के अंत में है। और, सामान्य रूप से प्रोग्रामिंग में, विभिन्न आवश्यकताओं और विभिन्न अनुप्रयोगों का सुझाव एक नया प्रकार है।

रेंज-v3 पुस्तकालय (है कि एक अवधारणा के माध्यम से कार्यान्वित किया जाता है) एक धारणा में इस अवलोकन बदल जाता है: यह end() के लिए एक नए प्रकार का परिचय और केवल आवश्यकता है कि यह समानता-तुलनीय इसी इटरेटर के साथ है - लेकिन आवश्यकता नहीं है सामान्य इटरेटर ऑपरेशंस)। इस नए प्रकार के end() को सेंटीनेल कहा जाता है।

यहां मुख्य लाभ प्राप्त अवशोषण और चिंताओं का बेहतर अलगाव है, जिसके आधार पर संकलक संभवतः बेहतर अनुकूलन करने में सक्षम है।

struct my_iterator; //some iterator 
struct my_sentinel 
{ 
    bool is_at_end(my_iterator it) const 
    { 
     //here implement the logic when the iterator is at the end 
    } 
}; 

auto operator==(my_iterator it, my_sentinel s) //also for (my_sentinel s, my_iterator it) 
{ 
    return s.is_at_end(it); 
} 

अमूर्त देखें: कोड में, मूल विचार यह (यह सिर्फ स्पष्टीकरण के लिए है और सीमा-v3 पुस्तकालय के साथ कोई संबंध नहीं है) है? अब, आप किसी भी जैसे जाँच आप is_at_end समारोह में चाहते हैं, को लागू कर सकते हैं: कभी नहीं

  • रोक N वेतन वृद्धि के बाद (एक अनंत श्रेणी प्राप्त)
  • स्टॉप (एक गिना रेंज पाने के लिए)
  • रोक जब एक \0 का सामना करना पड़ रहा है, यानी *it = '\0' (सी-स्ट्रिंग्स पर लूपिंग के लिए)
  • 12'o घड़ी (दोपहर के भोजन के लिए) बंद होने पर रोकें, और इसी तरह।

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


(*) ध्यान दें कि इसका मतलब यह नहीं है कि सामान्य रूप से इस तरह के संचालन के लिए कोई उपयोग नहीं है।उदाहरण के लिए, --end() कुछ स्थानों पर उपयोगी हो सकता है, उदाहरण के लिए देखें this question। हालांकि, इनके बिना मानक लाइब्रेरी को लागू करना संभवतः संभव है - यह रेंज-वी 3 लाइब्रेरी ने किया है।

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