2012-04-23 12 views
12

में lambda के लिए std :: unique_ptr "move by" कैप्चर करने के लिए कैसे करें I C++ 11 में नई विशेषताएं सीख रहे हैं और इस समस्या से आ गए हैं। मैं for_each के लिए तर्क के रूप में इसे लैम्ब्डा के अंदर ले जाकर एक अद्वितीय_ptr को कैप्चर करना चाहता हूं।std :: for_each

की स्थापना:

std::array<int,4> arr = {1,3,5,6}; 
std::unique_ptr<int> p(new int); (*p) = 3; 

प्रयास 1 - क्योंकि unique_ptr एक प्रति निर्माता नहीं है काम नहीं करता। सी ++ 0x चाल वाक्यविन्यास द्वारा पास निर्दिष्ट नहीं करता है।

std::for_each(arr.begin(), arr.end(), [p](int& i) { i+=*p; }); 

प्रयास 2 - उपयोग बाँध एक समारोह के लिए पी के लिए ले जाया गया प्रतिलिपि बाध्य करने के लिए है कि पूर्णांक & लेता है:

std::for_each(arr.begin(), arr.end(), 
    std::bind([](const unique_ptr<int>& p, int& i){ 
      i += (*p); 
    }, std::move(p)) 
); 

संकलक शिकायत है कि 'result' : symbol is neither a class template nor a function template.

व्यायाम का मुख्य उद्देश्य के लिए है समझें कि बाद में उपयोग के लिए कैश किए गए लैम्ब्डा में एक जंगम चर कैसे पकड़ा जाए।

+0

यह प्रश्न पहले ही पूछा जा चुका है [यहां] (http://stackoverflow.com/q/8640393/20984)। हालांकि, मैं बंद करने के लिए वोट नहीं देता क्योंकि आपके प्रश्न में एक वैकल्पिक (हालांकि काम नहीं कर रहा) समाधान है। –

+0

यह भी देखें [यहां] (http://stackoverflow.com/q/8236521/20984)। –

उत्तर

18

अपडेट: आप सी ++ 14 से लैम्ब्डा में एक जंगम चर को कैप्चर कर सकते हैं।

std::for_each(arr.begin(), arr.end(), [p=std::move(p)](int& i) { i+=*p; }); 

आप सी ++ 11 में किसी भी सरल तरीके से एक लैम्ब्डा में एक जंगम चर पर कब्जा नहीं कर सकते हैं।

प्रतिलिपि या संदर्भ द्वारा लैम्ब्डा कैप्चर। इस प्रकार, एक चाल-केवल परिवर्तनीय को कैप्चर करने के लिए, आपको इसे उस ऑब्जेक्ट में लपेटना होगा जहां कॉपी करना => चलाना (जैसे std::auto_ptr)। यह एक बुरा हैक है।

अपने उदाहरण में, आप केवल संदर्भ द्वारा कब्जा कर सकते हैं, लेकिन अगर यह सिर्फ कोड को सरल बनाया गया था कि यह क्या आप वास्तविक कोड के साथ करना चाहता था कार्य न करें:

std::for_each(arr.begin(), arr.end(), [&p](int& i) { i+=*p; }); 

यहाँ एक ही कॉपी-चाल-आवरण है:

template<typename T> 
struct move_on_copy_wrapper 
{ 
    mutable T value; 

    move_on_copy_wrapper(T&& t): 
     value(std::move(t)) 
    {} 

    move_on_copy_wrapper(move_on_copy_wrapper const& other): 
     value(std::move(other.value)) 
    {} 

    move_on_copy_wrapper(move_on_copy_wrapper&& other): 
     value(std::move(other.value)) 
    {} 

    move_on_copy_wrapper& operator=(move_on_copy_wrapper const& other) 
    { 
     value=std::move(other.value); 
     return *this; 
    } 

    move_on_copy_wrapper& operator=(move_on_copy_wrapper&& other) 
    { 
     value=std::move(other.value); 
     return *this; 
    } 

}; 

फिर आप इसे इस तरह उपयोग कर सकते हैं:

int main() 
{ 
    std::unique_ptr<int> p(new int(3)); 
    move_on_copy_wrapper<std::unique_ptr<int>> mp(std::move(p)); 

    [mp]() 
    { 
     std::cout<<"*mp.value="<<*mp.value<<std::endl; 
    } 
    (); 

    std::cout<<"p="<<p.get()<<", mp="<<mp.value.get()<<std::endl; 
} 
+0

क्या आपको वास्तव में * गति * अर्थपूर्ण कार्यों को लागू करने की आवश्यकता है, यानी 'move_on_copy_wrapper (move_on_copy_wrapper &&)' और 'move_on_copy_wrapper & operator = (move_on_copy_wrapper &&)'? संकलित जेनरेटर पर्याप्त नहीं हैं? – Nawaz

+1

संकलक उन्हें कॉपी कन्स्ट्रक्टर के अस्तित्व और कॉपी असाइनमेंट ऑपरेटर के कारण उत्पन्न नहीं करेगा। –

+1

"ध्यान दें कि std :: bind को यह भी आवश्यक है कि इसके तर्क कॉपी करने योग्य हों।" यह सच नहीं है। 'std :: bind' केवल-चाल प्रकारों के साथ प्रयोग योग्य है। –

2

आपका प्रयास 2 almo होगा सेंट काम

क्या अनुपलब्ध है आप एक पैरामीटर उम्मीद करने के लिए अपने bind कॉल नहीं बताया है है:

std::for_each(arr.begin(), arr.end(), 
    std::bind([](const unique_ptr<int>& p, int& i){ 
     i += (*p); 
    }, std::move(p), std::placeholders::_1) 
); 

placeholders::_1 है कि यह एक पैरामीटर अपने operator() के लिए यह करने के लिए पारित कर दिया की उम्मीद करनी चाहिए bind का परिणाम बताने के लिए आवश्यक है।

यह @ marton78 के उत्तर here में दिए गए सुझाव भी है।

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