2012-12-05 12 views
12

साथ जमा मैं निम्नलिखित कोडC++ के बजाय कदम प्रतिलिपि

auto adder = [](string& s1, const string& s2)->string&& 
    { 
     if (!s1.empty()) 
     s1 += " "; 
     s1 += s2; 
     return move(s1); 
    }; 

    string test; 
    test.reserve(wordArray.size() * 10); 
    string words = accumulate(wordArray.begin(), wordArray.end(), 
     move(test), adder); 

क्या मैं यहाँ चाहते हैं स्ट्रिंग नकल से बचने के लिए है। दुर्भाग्यवश यह जमा करने के बनाम 2012 के कार्यान्वयन द्वारा पूरा नहीं किया गया है। आंतरिक रूप से अन्य फ़ंक्शन कॉल जमा करें _ प्रक्रिया और प्रक्रिया में रैवल्यू कार्यक्षमता खो जाती है।

यह मैं बजाय इतना

string words = _Accumulate(wordArray.begin(), wordArray.end(), 
    move(test), adder); 

मैं इरादा प्रदर्शन लाभ मिल की तरह _Accumulate फ़ंक्शन को कॉल करें।

क्या आरडीडी लाइब्रेरी को रावल्यू तर्कों को ध्यान में रखने के लिए लिखा जाना चाहिए?

क्या कोई अन्य तरीका है जिसे मैं धोखा देने के बिना जो कुछ भी चाहता हूं उसे पूरा करने के लिए जमा कर सकता हूं?

+1

अपने 'test' एक rvalue नहीं है। लैम्ब्डा में 's1' एक रैवल्यू –

उत्तर

4

हाल की पोस्ट को सी ++ 11 ड्राफ्ट (N3337.pdf) हम देख सकते हैं कि std :: संचित के प्रभाव निर्दिष्ट किया जाता है

रूप

साथ संचायक एसीसी आरंभ करके अपने परिणाम की गणना से एक जाँच हो रही है प्रारंभिक मान init और फिर क्रम में [पहले, अंतिम) श्रेणी में प्रत्येक iterator के लिए acc = acc + * i या acc = binary_op (acc, * i) के साथ संशोधित करता है।

तो, मानक वास्तव में कार्यान्वयन कि एसटीडी का उपयोग :: इस तरह वर्ष संचायक मूल्य के लिए ले जाने के मनाही:

template <class InputIterator, class T, class BinOp> 
T accumulate (InputIterator first, InputIterator last, T init, BinOp binop) 
{ 
    while (first!=last) { 
    init = binop(std::move(init), *first); 
    ++first; 
    } 
    return init; 
} 

जो आपके मामले में दुर्भाग्यपूर्ण है।

विकल्प (1): इस कदम-जागरूकता को लागू करें स्वयं को जमा करें।

विकल्प (2): जैसे

struct mutating_string_adder { 
    string operator()(string const& a, string const& b) const {return a+b;} 
    string operator()(string & a, string const& b)  const {a += b; return std::move(a);} 
    string operator()(string && a, string const& b)  const {a += b; return std::move(a);} 
}; 

ध्यान दें कि मैं नहीं उपयोग rvalue संदर्भ वापसी प्रकार यहाँ किया एक functor का उपयोग करते रहें। यह जानबूझकर है क्योंकि यह संदर्भ मुद्दों को लटकने से बच सकता है, उदाहरण के लिए जहां अंतिम अधिभार उठाया गया है और 'ए' अस्थायी वस्तु को संदर्भित करने के लिए प्रारंभ किया गया है। स्ट्रिंग के लिए सभी ऑपरेटर + अधिभार भी जानबूझकर मूल्य से वापस आते हैं।

इसके अलावा आप std :: stringstream और आउटपुट स्ट्रीम इटरेटर के साथ संयोजन में std :: प्रतिलिपि का उपयोग करना चाह सकते हैं।

परिशिष्ट: कुछ आंशिक सही अग्रेषण के साथ वैकल्पिक mutating_string_adder:

struct mutating_string_adder { 
    template<class T, class U> 
    std::string operator()(T && a, U && b) const { 
    return std::move(a) + std::forward<U>(b); 
    } 
}; 
+0

'mutating_string_adder' नहीं है - दूसरा ऑपरेटर(), एक लवल्यू है, इसलिए चाल कुछ भी नहीं करती है। हालांकि, मुझे यकीन नहीं है कि पहले ऑपरेटर() को चाल का उपयोग करना चाहिए या नहीं। –

+0

@ BЈовић: std :: move का उद्देश्य एक लालू को एक रैवल्यू में बदलना है। तो, निश्चित रूप से, std :: move कुछ करता है। अगर मैंने रिटर्न स्टेटमेंट में चारों ओर std :: move को हटा दिया है, तो वापसी मूल्य की बजाय प्रतिलिपि बनाई गई प्रतिलिपि बनाई जाएगी। पहले अधिभार के लिए std :: move का उपयोग करने की आवश्यकता नहीं है क्योंकि एक + बी पहले से ही एक रावल्यू है। – sellibitze

+0

चाल-जागरूक संचय किसी भी प्रतियों के साथ ठीक काम करता है और उसी आरक्षित क्षेत्र का उपयोग –

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