2010-10-19 19 views
20

मेरा प्रश्न निश्चित रूप से सी ++ वाक्यविन्यास से परिचित किसी के लिए एक साधारण है। मैं सिर्फ सी ++ सीख रहा हूं और यह होमवर्क का प्रकार है।सी ++ में इटरेटर से मूल्य प्रकार कैसे प्राप्त करें?

template<typename Iter> 
void quickSort(Iter begin, Iter end) 
{   
    //.. 
    auto pivot = * (begin + (end - begin)/2); 
    //.. 
} 

पिवट को [प्रारंभ, अंत] अंतराल के केंद्र से मूल्य होना चाहिए। Ite मैंने जो कोड लिखा है वह काम करता है, लेकिन auto भाषा के नए स्टैंडआर्ट से एक कीवर्ड है। इसे पुराने तरीके से कैसे करें? auto के बजाय क्या लिखना है? यदि आपके टेम्पलेट Iter एक सूचक प्रकार के रूप में साथ instantiated है

+18

यही वह है जिसे मैं देखना चाहता हूं। कोई भी जो इटरेटर और 'ऑटो' का उपयोग कर सी ++ सीख रहा है। :) – jalf

उत्तर

23

typename std::iterator_traits<Iter>::value_type

यह काम करेंगे।

वैसे, typename इस प्रकार का हिस्सा नहीं है। यह संकलक को बताता है कि value_type वास्तव में एक प्रकार है। यदि यह किसी फ़ंक्शन या स्थिर डेटा सदस्य का नाम था, तो यह वाक्यविन्यास को प्रभावित करता है। संकलक को यह आवश्यक नहीं है कि यह क्या है, क्योंकि iterator_traits के Iter के लिए विशेषज्ञता टेम्पलेट संकलित होने पर दिखाई नहीं दे सकती है।

+1

यह सबसे अच्छा संभव समाधान है, लेकिन यह इंगित करने लायक है कि यह एक सामान्य समाधान नहीं है। यह सब कुछ के साथ काम करने की गारंटी नहीं है जिसे उपयोगकर्ता एक पुनरावर्तक के रूप में पास करने का प्रयास कर सकता है ... उन्हें अभी भी उनके इटरेटर ऑब्जेक्ट में value_type जोड़ने की आवश्यकता हो सकती है (या लक्षणों के लिए विशेषज्ञता बनाएं)। एक विकल्प केवल इटरेटर्स का उपयोग जारी रखने के लिए है, और पिवट के लिए एक इटरेटर बनाने के लिए, इसे आवश्यक रूप से dereferencing, templated समारोह के अंदर मूल्य प्रकार की आवश्यकता के बिना। –

+3

@ टोनी: यह सच है, और उस कारण से 'ऑटो' बेहतर है। हालांकि, सभी मानक एल्गोरिदम के लिए उपयोगकर्ता को 'iterator_traits' (24.3.1) कुछ ऐसा करने की आवश्यकता होती है, और यह उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन टेम्पलेट्स के लिए समान प्रतिबंध होने के लिए उचित है। जो लोग इटरेटर लिखते हैं, वे 'std :: iterator' का उपयोग बेस क्लास के रूप में कर सकते हैं ताकि * इटेटरेटर में पास करने के लिए * कोशिश * के बीच के अंतर को पार करने के लिए और वास्तव में 'Iterator' में गुज़रने के लिए अंतर हो सके ;-) –

+1

@Steve: हाँ, बिल्कुल (और आपको पहले से ही एक +1 मिला है)। –

1

स्टीव का उत्तर सही है; सी ++ 98 में, आपको std :: iterator_traits का उपयोग करना होगा या आप Iter :: value_type का उपयोग कर सकते हैं यदि आप जानते हैं कि इटरेटर में यह टाइपपीफ है (उदा। std :: iterator से लिया गया है)। हालांकि, आपके कोड में एक और समस्या है: आप आमतौर पर इसे इटरेटर्स को विभाजित नहीं कर सकते हैं। यह निश्चित रूप से पॉइंटर्स के साथ काम करता है, लेकिन अधिक सामान्य मामले में नहीं। एक और सामान्य दृष्टिकोण होगा:

Iter itPivot = std::advance(begin, std::distance(begin, end)/2); 
+0

मूल कोड इटरेटर को विभाजित नहीं करता है, और यह काम नहीं करेगा, पॉइंटर्स के साथ भी नहीं। कोड इसके बजाय घटाव का उपयोग करता है, जो सभी यादृच्छिक अभिगम इटरेटर पर काम करता है (न केवल पॉइंटर्स)। और चूंकि क्विकॉर्ट को अन्य इटरेटर प्रकारों के लिए क्रमबद्ध किया जाएगा (वैसे भी एक कुशल कार्यान्वयन), यहां 'ऑपरेटर -' का उपयोग ठीक है। –

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