2015-12-30 5 views
6

इतना आसान सवाल है।std :: copy_n std :: size_t के बजाय टेम्पलेट पैरामीटर क्यों लेता है?

template<class InputIt, class Size, class OutputIt> 
OutputIt copy_n(InputIt first, Size count, OutputIt result); 

क्यों std::copy_n तत्वों यह बस std::size_t के बजाय कॉपी करने के लिए जा रहा है की संख्या के लिए एक प्रकार का होता है? मैं सिर्फ एक कारण के बारे में सोच नहीं सकता।

template<class InputIt, class OutputIt> 
OutputIt copy_n(InputIt first, std::size_t count, OutputIt result); 
+1

मान लें कि डेवलपर अचानक पैरामीटर गिनती के साथ उस फ़ंक्शन को कॉल करता है, एक 'हस्ताक्षरित int' है और इसका नकारात्मक मान है, यदि 'count'' std :: size_t' है, तो यह अभिन्न प्रचार करेगा, फिर हमें एक प्राप्त होगा अपरिभाषित व्यवहार। – Danh

+2

एक स्पष्ट मामला तब होता है जब आकार आकार 'size_t' –

उत्तर

6

मूल तर्क बारे में अटकलें ज्यादातर इस तरह के एक मामले में व्यर्थ है, लेकिन इस डिजाइन के साथ copy_n जैसे की नकारात्मक गिनती के साथ लागू किया जा सकता है int या ptrdiff_t प्रकार, इस मामले में यह केवल कुछ भी नहीं करता है, और यह निश्चित रूप से मानकीकरण समिति के सदस्यों को स्पष्ट कर दिया जाना चाहिए, जो बहुत सक्षम लोग हैं।


एक अतिरिक्त लाभ यह है कि इस तरह के इनपुट और आउटपुट iterators के रूप में विशेष iterators, साथ, आकार किसी भी संभावित सूचक अंतर से भी बड़ा हो सकता है, और इसलिए संभवतः से बड़ा size_t का प्रतिनिधित्व कर सकते हैं। जैसे यह 32-बिट विंडोज़ में 4 जीबी से बड़ी फ़ाइलों के लिए है। copy_n की परिभाषा स्पष्ट सूचक/इटरेटर अंकगणितीय, “ प्रत्येक गैर-ऋणात्मक पूर्णांक i < n के लिए व्यक्त की जाती है, *(result + i) = *(first + i) ” निष्पादित करती है, जो वास्तव में बहुत ही विशेष मामलों में इस लाभ को प्रस्तुत करने लगती है, लेकिन नोटेशन शुद्ध इनपुट और आउटपुट इटरेटर्स को समायोजित करता है के रूप में

सी ++ 11 §25.1/12 में विस्तार से बताया:

एल्गोरिदम ऑपरेटरों + और - के विवरण में इटरेटर श्रेणियों में से कुछ के लिए उपयोग किया जाता है जो के लिए वे की जरूरत नहीं है परिभाषित। इन मामलों में a+n के शब्दों

X tmp = a; 
advance(tmp, n); 
return tmp; 

और b-a की कि return distance(a, b) के रूप में ही है की तरह ही है,


डिजाइन के genericity कोई निहित लाभ, बल्कि यह अपने आप में एक नुकसान यह है कि इसे और अधिक वर्बोज़ है और कम आसानी से उत्पन्न समझा गलत उपयोग कोड के लिए निदान में है है। इसके फायदे में ऊपर सूचीबद्ध दो शामिल हैं। स्पष्ट रूप से समिति ने महसूस किया कि इन फायदों, और शायद अन्य (?) ने टेम्पलेट पैरामीटर के रूप में Size रखने के अंतर्निहित नुकसान से अधिक है।

+0

के अधिकतम मान से बड़ा हो सकता है, वे निर्दिष्ट कर सकते थे कि जब तक एक हस्ताक्षरित पूर्णांक प्रकार के साथ नहीं कहा जाता है तो व्यवहार को अपरिभाषित किया जाएगा। क्योंकि std :: copy_n का पूरा विचार तत्वों की एन-राशि की प्रतिलिपि बनाना है। नकारात्मक नहीं हो सकता है, गैर-अभिन्न नहीं हो सकता है, क्योंकि हम कई तत्वों से निपट रहे हैं। – DeiDei

+2

@ डीईडीई: तथ्य यह है कि डिजाइन जैसा है, यह इंगित करता है कि समिति के सदस्य आपके दृष्टिकोण से असहमत हैं। हां यह एक अधिकार तर्क है। मैंने पाया है कि ऐसे प्राधिकरण तर्क केवल वे हैं जो वास्तविकता की जानबूझकर अज्ञानता के खिलाफ प्रभावी हैं। –

+2

@ डीईडीई: कंटेनर आकारों के लिए हस्ताक्षरित प्रकारों का उपयोग करने के लिए तर्कसंगत (हालांकि आईएमएचओ विश्वास नहीं कर रहे हैं) तर्कसंगत हैं: जबकि मैं उस और अन्य विषयों पर जितना अधिक कहता हूं उससे असहमत हूं, लक्ष्को उन्हें अपने बड़े पैमाने पर सी ++ पुस्तक में विज्ञापन विसंगति बताते हैं दिलचस्पी है, लेकिन सबसे अच्छा 'abs (c1.size() - c2.size()) के बेवकूफ/अंतर्ज्ञानी उपयोग का समर्थन कर रहा है। इसके अलावा, अवांछित मैक्रोज़ जैसी चीजें आकार प्रदान करने के लिए उपयोग की जा सकती हैं, और जब तक कि बहुत बड़ी न हो तो 'int' तक डिफ़ॉल्ट हो जाएगी। * अपरिभाषित व्यवहार * होने पर * ऐसे प्रकारों को आकस्मिक रूप से 'copy_n' पर पास किया जाता है, यह पूरी तरह से अनावश्यक और * बहुत * खतरनाक विचार है। –

3

मुझे लगता है कि यह जेनेरिकिटी की वजह से है।
कंटेनर size_type सी ++ में आमतौर पर size_t होते हैं। लेकिन यदि आप एक कस्टम कंटेनर का उपयोग करते हैं, या कस्टम आवंटकों का उपयोग करते हैं, तो हो सकता है कि यह मामला टेम्पलेट पैरामीटर न हो।

एक custom container के लिए, size_typesize_t करने के लिए एक typedef होने की जरूरत नहीं है (यह an unsigned integer large enough to represent all positive values of difference_type हो गया है)।

एसटीएल कंटेनरों के लिए, size_typeallocator::size_type करने के लिए एक typedef जो default allocator के लिए size_t है। लेकिन यदि आप एक कस्टम आवंटक निर्दिष्ट करते हैं तो यह प्रकार भिन्न हो सकता है।

+0

यह 'iterator_traits :: difference_type' हो सकता है। और निर्दिष्ट करें कि 'दूरी (परिणाम, वापसी_वर्त) == गिनती'। लेकिन फिर इनपुट-केवल और आउटपुट-केवल इटरेटर्स के लिए इसका अस्पष्ट अर्थ होगा। –

+0

@ कॉन्स्टेंटिन बर्नोव: सी ++ में 11 'copy_n' को "प्रत्येक गैर-ऋणात्मक पूर्णांक i

+0

ओह, यह सी ++ 11 §25.1/12 में परिभाषित किया गया है। फिर भी कुछ सीख लिया। अभी तक मर नहीं है, hallelujah! ओह, डांग, मैं नास्तिक हूँ। वैसे फिर भी। –

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