2012-08-01 8 views
15
//------------------------------------------------------------------------------ 
struct A 
{ 
    A(){} 
    A(A&&){} 
    A& operator=(A&&){return *this;} 
    void operator()(){} 

private: 
    A(const A&); 
    A& operator=(const A&); 

    int x; 
}; 

//------------------------------------------------------------------------------ 
int main() 
{ 
    A a; 
    std::function<void()> func(std::move(a)); 
} 

'ए :: ए': निजी सदस्य कक्षा में 'ए'क्यों C++ 11 एक noncopyable functor को std :: function में नहीं ले जा सकता है?

घोषित जब मैं संदर्भ या const से कुछ पर कब्जा मैं एक गैर copyable लैम्ब्डा कर सकते हैं की तरह लगता है का उपयोग नहीं कर सकते हैं। हालांकि जब मैं ऐसा करता हूं तो यह वास्तव में std::function को देने के लिए काम करता है।

+1

एक [वर्कअराउंड] (https://gist.github.com/vmilea/5815777) के रूप में, आप std :: function और अपने functor के बीच एक प्रतिलिपि एडाप्टर डाल सकते हैं। एडाप्टर में एक डमी (मूव-ऑन-कॉपी) कॉपी कन्स्ट्रक्टर है और कॉपी होने पर फेंकता है। –

उत्तर

19

संक्षिप्त उत्तर यह है कि सी ++ 11 विनिर्देश के लिए ACopyConstructiblestd::function के साथ उपयोग करने के लिए आवश्यक है।

लंबा उत्तर यह आवश्यकता मौजूद है क्योंकि std::function कन्स्ट्रक्टर के भीतर आपके मज़ेदार के प्रकार को मिटा देता है। ऐसा करने के लिए, std::function वर्चुअल फ़ंक्शंस के माध्यम से अपने मज़ेदार के कुछ सदस्यों तक पहुंच जाना चाहिए। इनमें कॉल ऑपरेटर, कॉपी कन्स्ट्रक्टर और विनाशक शामिल हैं। और चूंकि इन्हें वर्चुअल कॉल के माध्यम से एक्सेस किया जाता है, इसलिए वे वास्तव में std::function की कॉपी कन्स्ट्रक्टर, विनाशक या कॉल ऑपरेटर का उपयोग करते हैं या नहीं।

+0

अगर मैं गलत हूं (और शायद मैं हूं) लेकिन मुझे वर्चुअल फ़ंक्शंस का उपयोग करने के लिए सही करें, तो आपको एक vtable और इसलिए बेस क्लास की आवश्यकता है। इस मामले में आधार वर्ग कौन सा है? – akappa

+5

कैसे प्रकार विलोपन काम करता है के वर्णन के लिए http://stackoverflow.com/questions/6324694/type-erasure-in-c-how-boostshared-ptr-and-boostfunction-work देखें। बेस क्लास std :: function का कार्यान्वयन विवरण है। व्युत्पन्न वर्ग भी कार्यान्वयन विस्तार है, लेकिन आपूर्ति किए गए मज़ेदार पर भी टेम्पलेट किया गया है। –

+0

बहुत रोचक, धन्यवाद। – akappa

-1

यह विजुअल स्टूडियो में एक बग है। यह एक प्रतिलिपि बनाने की कोशिश करता है (जब वास्तव में इसे एक चाल को आगे बढ़ाने की कोशिश करनी चाहिए), जिसके लिए एक सुलभ प्रतिलिपि बनाने की आवश्यकता होती है। सबसे अच्छा समाधान कॉपी कन्स्ट्रक्टर/असाइनमेंट ऑपरेटर घोषित करना है और उन्हें कभी परिभाषित नहीं करना है। कक्षा अभी भी गैर-प्रतिलिपि होगी लेकिन कोड संकलित होगा, क्योंकि वीएस कभी भी कॉपी कन्स्ट्रक्टर को कॉल करने का प्रयास नहीं करेगा।

+3

यह स्पष्ट रूप से प्रतिलिपि ctor को कॉल करने का प्रयास करता है यदि मैं सुझाव देता हूं, क्योंकि मुझे इसके लिए एक अनसुलझा बाहरी मिलता है। – David

+0

@ डेव: हाँ, यही कारण है कि यह एक * बग * है। मानक कहता है कि इसकी अनुमति दी जानी चाहिए, लेकिन वीएस सही नहीं करता है। –

+0

@ निकोलबोलस यह ठीक है, लेकिन उनके कामकाज के सुझाव काम नहीं कर पाए। मुझे यह कहने की अनुमति नहीं है? (हालांकि, डेडएमजी के जवाब में मैं सराहना करता हूं, धन्यवाद) – David