2012-11-26 14 views
5

मुझे अभी पता चला है कि विजुअल स्टूडियो सी ++ 2010 में, basic_string::append (iter, iter), जाहिर है, std::copy का उपयोग करके लागू नहीं किया गया है।बुनियादी_स्ट्रिंग क्यों नहीं है :: संलग्न (iter, iter) कॉल std :: copy?

पहला सवाल:

अब मैं अपने खुद के इटरेटर प्रकार लागू, एक साथ आदेश और अधिक कुशल ब्लॉक के लिहाज से नकल प्रदान करने के लिए मेरी इटरेटर प्रकार के लिए std::copy की एक अनुकूलित अधिक भार के साथ लगता है। append ओवरलोडिंग के अलावा, इस अनुकूलन का उपयोग करने के लिए basic_string::append प्राप्त करने का कोई तरीका है?

क्या कोई मौका है कि basic_string::append (iter, iter) चरित्र-प्रतिलिपि प्रतिलिपि नहीं करता है?

दूसरा सवाल (मेरे अपने कार्यान्वयन के लिए एक प्रारंभिक बिंदु के रूप में):

वैध होने की गारंटी पीछा कर रहा है?

std::string t ("JohnB"); 
std::string s; 
s.reserve (10); 
std::copy (t.begin(), t.end(), s.begin()); 
s.push_back ('\0'); 

या मुझे बेहतर back_inserter का उपयोग करना चाहिए? अगर मैं back_inserter का उपयोग करता हूं - मैं चरित्र-प्रतिलिपि प्रतिलिपि से कैसे बच सकता हूं?

+0

अपने दूसरे प्रश्न का उत्तर देने के लिए: 'रिजर्व()' के बाद 'प्रतिलिपि() 'निश्चित रूप से __not वैध__ नहीं है। प्रतिलिपि देखने के लिए प्रतिलिपि के बाद 's.size() 'प्रिंट करें। – Blastfurnace

+0

@ ब्लास्टफर्नस: लेकिन 'प्रतिलिपि()' के बाद 'प्रतिलिपि() 'काम करेगा। –

+0

'प्रतिलिपि' के बाद 'प्रतिलिपि' के बारे में क्या? – JohnB

उत्तर

2

std::basic_string<cT, ...>::append() की परिभाषा में कुछ समय सौंपने से पहले यह अंततः अधिभार (21.4.6.2 [स्ट्रिंग :: संलग्न] पैरा 7) पर आता रहता है:

basic_string& append(const charT* s, size_type n);

इस बिंदु पर स्पष्ट रूप से मूल अनुयायियों में से कोई भी नहीं छोड़ा गया है। मामले में आप आश्चर्य है क्या, इनपुट इटरेटर आप append() के लिए पारित हो सकता है के लिए होता ही अनुच्छेद के पैरा 17 में अधिभार जिसमें कहा गया है द्वारा हटा दिया गया:

प्रभाव: append(basic_string(first, last)) के बराबर।

कुछ मध्यवर्ती राज्य में। यदि मानक लाइब्रेरी को इस तरह कार्यान्वित किया जाता है क्योंकि इसे मानक रूप से मानक कहा जाता है तो स्पष्ट रूप से std::copy() पर कोई कॉल नहीं है।

हालांकि, आप वास्तव में std::copy() के अपने अधिभारित संस्करण को देखने में सक्षम नहीं होंगे। क्या पुस्तकालय ऐसा कर सकते हैं

template <typename InIt> 
std::basic_string<cT, ...>& std::basic_string<cT, ...>::append(InIt begin, InIt end) { 
    if (is_forward_iterator<begin>::value) { 
     this->reserve(this->size() + std::distance(begin, end)); 
    } 
    std::copy(begin, end, back_inserter_without_capacity_check<InIt>(*this); 
} 

का नैतिक बराबर है अब, अन्य रोचक सा है: यहां तक ​​कि अगर यह है कि यह कैसे लागू किया है, यह वास्तव में std::copy() के संबंध में आपकी मदद नहीं करता है! आप std::copy() आंशिक रूप से विशेषज्ञ नहीं कर सकते हैं (ठीक है, आप किसी भी फ़ंक्शन टेम्पलेट को आंशिक रूप से विशेषज्ञ नहीं कर सकते हैं) और लक्ष्य इटरेटर का प्रकार परिभाषित नहीं किया गया है (उपर्युक्त कार्यान्वयन में यह std::back_inserter() का गैर-क्षमता जांच संस्करण होगा यदि InIt एक आगे इटरेटर है और अन्यथा यह std::back_inserter() जैसा ही होगा।

+0

एचएम, लेकिन अगर कार्यान्वयन 'नामस्थान std का उपयोग कर रहे थे; ...; प्रतिलिपि बनाएँ (प्रारंभ करें, अंत, ...) ', फिर मैं इटरेटर वर्ग के नामस्थान में अपने इटरेटर वर्ग (प्रथम और दूसरे तर्क के रूप में) के लिए' प्रतिलिपि 'को परिभाषित कर सकता हूं, और' प्रतिलिपि 'का मेरा संस्करण एडीएल द्वारा पाया जाएगा। मुझे वास्तव में नहीं लगता कि 'संलग्न (कॉन्स char *, size_type)' को प्रतिनिधि देने का मानक कार्यान्वयन एक अच्छा विचार है, क्योंकि इसमें जरूरी है कि पहले एक वर्ण सरणी बनाना शामिल हो। – JohnB

+0

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

5

स्ट्रिंग क्लास की अपनी विशेषता वर्ग है जो उसके द्वारा वर्णित वर्णों पर किए जा सकने वाले संचालन को परिभाषित करती है।

(अधिक सामान्य std::copy के बजाय) char रों कॉपी करने के basic_string<char>std::char_traits<char>::copy का प्रयोग करेंगे। यह संभवतः मानक सी लाइब्रेरी में memcpy फ़ंक्शन पर मानचित्र करता है।

+0

कोई कारण नहीं है कि कोई नहीं हो सकता 'memdpy' पर मैप करने के लिए 'std :: copy (const char *, const char *, char *)' के लिए अधिभार भी। –

+0

वहां बहुत अच्छा हो सकता है, लेकिन 'std :: string' इसका उपयोग नहीं कर सकता (सीधे, कम से कम), क्योंकि इसे' char_traits' वर्ग से गुजरना है। –

+0

असल में, मैं केवल 'traits :: length()' के प्रत्यक्ष संदर्भ देख सकता हूं, जब 'std :: basic_string' क्लास टेम्पलेट को 'सीटी कॉन्स *' द्वारा इंगित स्ट्रिंग की लंबाई निर्धारित करने की आवश्यकता होती है, और' लक्षण :: अक्षर मानों की तुलना करने के लिए :: eq() 'और' लक्षण :: तुलना() '। मुझे कोई आवश्यकता नहीं दिख रही है कि 'विशेषताएँ :: कॉपी()' को कॉल करने की आवश्यकता है! –