2011-06-23 13 views
13

मेरी जानकारी के लिए, इटरेटर श्रेणियों के पदानुक्रम इस प्रकार है:इनपुट इटरेटर्स का उपयोग किया जा सकता है जहां आगे इटरेटर की उम्मीद है?

Random access -> Bi-directional -> Forward -> Input 
              -> Output 

है न?

मैंने हमेशा सोचा था कि एक नियम था, कि यदि एक एल्गोरिदम एक विशेष प्रकार के इटरेटर की अपेक्षा करता है, तो आप श्रृंखला को श्रेणियों के इटरेटर प्रदान कर सकते हैं, लेकिन नीचे नहीं। तो मैं this answer पढ़ रहा था, जहां ildjarn सुझाता है (0 बाद में स्वयं को सही किया गया) std::ifstreamstd::istream_iterator और std::search के साथ फ़ाइल में डेटा खोजने के लिए सुझाव दिया गया है। मैं टिप्पणी करने वाला था कि आप ऐसा नहीं कर सकते हैं, क्योंकि search फॉरवर्ड इटरेटर्स की अपेक्षा करता है, और istream_iterator एक इनपुट इटरेटर है। लेकिन बस यह सुनिश्चित करने के लिए, मैंने यह कोशिश की:

std::istringstream iss("Elephant hats for sale."); 
std::istream_iterator<char> begin(iss), end; 

std::string sub("hat"); 
auto i = std::search(begin, end, sub.begin(), sub.end()); 

मुझे संकलन करने की उम्मीद नहीं थी, लेकिन ऐसा हुआ। हालांकि, परिणाम बेकार प्रतीत होते हैं क्योंकि यदि मैं इसका पालन करता हूं:

while(i != end) 
{ 
    std::cout << *i; 
    ++i; 
} 

कोई आउटपुट नहीं है। तो, मेरा सवाल यह है: क्या मेरा संकलक पर istream_iterator का उपयोग करके मेरी कॉल को अनुमति देने के लिए त्रुटि में है? या इस तरह की चीज को रोकने के कोई नियम नहीं हैं?

+0

मेरी स्पष्ट गलती के बाद से; -] मैंने इनपुट उत्तरकर्ताओं के लिए एक रैपर (बूस्ट.पीरिट से) के लिंक के साथ अपना उत्तर अपडेट किया जो उन्हें आगे इटरेटर्स के रूप में उपयोग के लिए उपयुक्त बनाता है। – ildjarn

उत्तर

17

इनपुट इटरेटर्स का उपयोग किया जा सकता है जहां आगे इटरेटर की उम्मीद है?

नंबर एक इनपुट इटरेटर और एक आगे इटरेटर के बीच अंतर यह है कि एक इनपुट इटरेटर एक "एकल पास" इटरेटर है, लेकिन एक आगे इटरेटर एक "बहु पास" इटरेटर है।

एक बार जब आप एक इनपुट इटरेटर अग्रिम करते हैं, तो आप अब सीमा में पिछले तत्वों तक नहीं पहुंच सकते हैं। यदि आप एक इनपुट इटरेटर की एक प्रति बनाते हैं, तो दोनों इटरेटर वैध रहते हैं जब तक आप उनमें से किसी एक को आगे नहीं बढ़ाते; तो दूसरा मान्य होना बंद कर देता है।

एक आगे इटरेटर के साथ, आप किसी भी समय अनुक्रम पर फिर से सक्रिय हो सकते हैं, आप एक बार में एक इटरेटर की कई उपयोग करने योग्य प्रतियां प्राप्त कर सकते हैं, आप एक साथ कई अनुक्रमकों को अनुक्रम में उपयोग कर सकते हैं, और आप एक को अस्वीकार कर सकते हैं जितनी बार आप इसे आगे बढ़ाने से पहले जितना चाहें उतना बार।

तो, मेरा प्रश्न यह है: क्या मेरा संकलक istream_iterator का उपयोग करके मेरी कॉल को खोजने की अनुमति देने में त्रुटि में है?

कोई नियम नहीं है कि संकलक को कोड को अस्वीकार कर देना चाहिए।

नियम यह है कि आपको फ़ंक्शन द्वारा आवश्यक सही प्रकार के इटरेटर को पास करना सुनिश्चित करना होगा। कभी-कभी यदि आप गलत प्रकार के इटरेटर को पास करते हैं तो आपको संकलन त्रुटि मिलती है। कभी-कभी प्रोग्राम संकलित होगा लेकिन सही तरीके से काम नहीं करेगा। कभी-कभी चीजें सही तरीके से काम करने लगती हैं। यदि आप फ़ंक्शन को कॉल करने की आवश्यकताओं का उल्लंघन करते हैं तो परिणाम अपरिभाषित होते हैं।


जेनेरिक एल्गोरिदम आमतौर पर यह सोचते हैं कि प्रकार तर्क वास्तव में प्रदान की आवश्यकताओं को पूरा करके अपने प्रकार मानकों के आधार पर आवश्यकताओं को लागू। इसलिए, उदाहरण के लिए, एक एल्गोरिदम जो केवल यादृच्छिक अभिगम इटरेटर्स के साथ काम करता है, कुछ ऑपरेशन करके इस आवश्यकता को "लागू" करेगा जो केवल यादृच्छिक अभिगम इटरेटर्स (उदा। it + 1) के साथ काम करता है।अगर इटेटरेटर उस ऑपरेशन का समर्थन नहीं करता है (operator+(iterator, int) यहां), कोड संकलित करने में विफल हो जाएगा।

समस्या यह है कि इनपुट इटरेटर के बीच अंतर करने और इसे इटरेटर्स को आगे बढ़ाने का कोई तरीका नहीं है: आप दोनों को बढ़ा और खराब कर सकते हैं; अंतर यह है कि आप उन परिचालनों में से कितनी बार प्रदर्शन कर सकते हैं और अनुक्रम जिसमें आप उन परिचालनों को कर सकते हैं। इसलिए, std::search जैसे एल्गोरिदम *it और ++it का उपयोग करेंगे, जो इनपुट इटरेटर्स के लिए ठीक से "काम" करेगा, कम से कम कोड के संकलन के रूप में।

सिद्धांत रूप में, एक एल्गोरिदम std::iterator_traits क्लास टेम्पलेट का उपयोग यह निर्धारित करने के लिए कर सकता है कि एक इटरेटर एक इनपुट इटरेटर या अग्रेषित इटरेटर है; मुझे नहीं पता कि सी ++ भाषा मानक द्वारा इसकी अनुमति होगी या नहीं। यदि लाइब्रेरी ने ऐसा किया है, तो आप अपने कोड के लिए संकलन त्रुटि प्राप्त कर सकते हैं, जो बेहतर होगा।

+0

तो यह अनिर्धारित व्यवहार है, मुझे इसके बारे में सोचना चाहिए था। धन्यवाद जेम्स। –

+0

"* मुझे नहीं पता कि सी ++ भाषा मानक द्वारा इसकी अनुमति होगी या नहीं। *" ऐसा क्यों नहीं होगा? यूबी के वैध अभिव्यक्ति को संकलित करने से इनकार नहीं कर रहा है? – ildjarn

+2

@ildjarn: मुझे नहीं पता कि यह आवश्यक है कि इटरेटर अवधारणाओं को पूरा करने के लिए एक प्रकार में सही 'iterator_category' टाइपपीफ है। मुझे लगता है कि _would_ की आवश्यकता हो, लेकिन न तो libstdC++ और न ही वीसी ++ कार्यान्वयन इसका लाभ उठाता है, इसलिए मुझे यकीन नहीं है। –

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