2015-08-24 6 views
5

मैं एक स्थिति है जिसमें काफी रोचक है के रूप में कोड मैं पर काम कर रहा हूँ संकलित भले ही मैं इसे तो मैं अपने ले के लिए आप से पूछना चाहते हैं करता है हैरान हूँ में मिल गया के साथ स्वचालित रूप से जनरेट चाल निर्माता।चल नहीं सदस्यों

स्थिति यह है। मैं नष्ट कर दिया चाल और कॉपी कंस्ट्रक्टर्स के साथ एक वर्ग है, जो उपयोगकर्ता परिभाषित असाइनमेंट ऑपरेटरों है है:

struct A { 
    A() { } 
    A(const A&) = delete; 
    A(A&&) = delete; 

    A& operator=(const A&) { return *this; } 
    A& operator=(A&&) { return *this; } 
}; 

और मैं A केवल सदस्य के रूप में के साथ एक और वर्ग है। इस वर्ग में मैं प्रति निर्माता परिभाषित लेकिन मैं डिफ़ॉल्ट के रूप में इस कदम निर्माता रखा और स्वैप समारोह के लिए एक कॉल के माध्यम से असाइनमेंट ऑपरेटर परिभाषित:

class B{ 
public: 
    A a; 

    B() 
    : a{} 
    { } 

    B(const B&) 
    : a{} 
    { } 

    B(B&& other) = default; 
}; 

int main() { 
    B b1; 
    B b2(std::move(b1)); // compiles?? 
} 

क्यों डिफ़ॉल्ट चाल निर्माता काम करते हैं, पर विचार करता है कि यह बस फोन नहीं कर सकते हैं चाल या कॉपी कन्स्ट्रक्टर ए? मैं जीसीसी 4.8.4 का उपयोग कर रहा हूँ।

उत्तर

7

मेरा मूल उत्तर गलत था, इसलिए मैं शुरू कर रहा हूं।


[class.copy] में, हम है:

एक डिफॉल्ट की कॉपी/एक दसवीं कक्षा के लिए चाल निर्माता नष्ट कर दिया के रूप में (8.4.3) यदि एक्स है परिभाषित किया गया है:
- [...]
- एक संभावित रूप से निर्मित सबोबजेक्ट प्रकार एम (या सरणी) जिसे प्रतिलिपि/स्थानांतरित नहीं किया जा सकता है क्योंकि ओवरलोड रिज़ॉल्यूशन (13.3), जैसा कि एम के संबंधित कंस्ट्रक्टर पर लागू होता है, परिणामस्वरूप अस्पष्टता या फ़ंक्शन होता है हटा दिया गया या डिफॉल्ट निर्माता से दुर्गम,
- [...] बुलेट बिंदु B(B&& other) = default; पर लागू होता है

यही कारण है, ताकि इस कदम निर्माता के रूप में नष्ट परिभाषित किया गया है। यह std::move() साथ संकलन को तोड़ने के लिए प्रतीत होता है, लेकिन हम भी (defect 1402 के संकल्प के माध्यम से) है:

एक डिफॉल्ट की चाल निर्माता के रूप में हटा दिया गया है अधिभार संकल्प (13.3, 13.4) द्वारा नजरअंदाज कर दिया परिभाषित किया गया है। [नोट: हटाई चाल निर्माता अन्यथा एक rvalue जो प्रतिलिपि निर्माता के बजाय का उपयोग कर सकते से प्रारंभ के साथ हस्तक्षेप करेगा। -end नोट]

अनदेखा करना कुंजी है। इस प्रकार, जब हम करते हैं:

B b1; 
B b2(std::move(b1)); 

हालांकि B के लिए कदम निर्माता हटा दी जाती है, इस कोड को अच्छी तरह से बनाई है, क्योंकि इस कदम निर्माता बस अधिभार संकल्प में भाग नहीं लेता और प्रतिलिपि निर्माता बजाय कहा जाता है। इस प्रकार, B MoveConstructible है - भले ही आप इसे अपने चालक कन्स्ट्रक्टर के माध्यम से नहीं बना सकते।

+0

मैं कॉपी और काम में COUTS के एक जोड़े को जोड़ कर उसे अपनी परिकल्पना है कि, सही ढंग से कदम निर्माता संकलन करने में असमर्थ है, यह केवल प्रतिलिपि में बदल जाती पुष्टि करने के लिए लगता है।मैं मानक की सूक्ष्मता का विशेषज्ञ नहीं हूं लेकिन ऐसा लगता है कि डिफ़ॉल्ट घोषणा एक टेम्पलेट – Triskeldeian

+0

में SFINAE की तरह व्यवहार करती है, हटाए गए रूप में परिभाषित एक डिफ़ॉल्ट चालक कन्स्ट्रक्टर को ओवरलोड रिज़ॉल्यूशन द्वारा अनदेखा किया जाता है। N4527 देखें [class.copy]/p11; भी [एन 3667] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3667.html) –

+0

@ टी.सी. सही के बारे में नया जवाब आवाज? – Barry

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