में लिपटे संकलित एक स्पष्ट संकलन त्रुटि के साथ इस कोड पर विचार करें,: (1)अधूरा प्रकार की नई जब टेम्पलेट
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
का उपयोग करते हुए एक unique_ptr
या तो मदद नहीं करेगा: (2)
struct A;
struct B {
B() { std::make_unique<A>(); } // error: due to ~unique_ptr()
};
तब (मेरे महान आश्चर्य करने के लिए) मुझे पता चला है कि इस होगा संकलन: (3)
struct A;
struct B {
B() { std::make_unique<A>(); }
};
struct A {}; // OK, when a definition is added **below**
तब मैं जाँच की, कि क्या यह रूप में अच्छी तरह new
साथ मदद करता है - नहीं: (4)
struct A;
struct B {
B() { new A(); } // error: allocation of incomplete type 'A'
};
struct A {};
मैं लगा यह template
के साथ और वास्तव में क्या करने के लिए कुछ न कुछ है: अंदर एक template
करताnew
लपेटकर संकलन: (5)
template <typename T>
T* my_new() { return new T(); } // OK, when wrapped in template
struct A;
struct B {
B() { my_new<A>(); }
};
struct A {};
और बस पूर्णता के लिए के लिए, A
की परिभाषा को हटाने के लिए फिर से एक त्रुटि को जन्म देती है: (6)
template <typename T>
T* my_new() { return new T(); } // error: allocation of incomplete type 'A'
struct A;
struct B {
B() { my_new<A>(); }
};
// do note: definition of A removed
यहां क्या हो रहा है? जहां तक मैं समझ गया, कंपाइलर A
के आकार/परिभाषा को आवंटित करने के लिए जानना चाहिए, इस प्रकार केवल इसे घोषित करना पर्याप्त नहीं है। इसके अलावा मुझे विश्वास था कि परिभाषा आवंटन से पहले होनी चाहिए।
new
सीधे (1,4) का उपयोग करते समय यह सही लगता है। लेकिन जब new
लपेटा गया है, तो यह स्पष्ट है कि मैं गलत हूं (2,3,5,6)।
संभावित स्पष्टीकरण मैं अब तक पाए जाते हैं: जब तक template
इन्स्टेन्शियशन होता
- पूरा प्रकार के लिए चेक देरी हो रही है। मुझे लगता है कि यह सही है, लेकिन मेरे मामले में प्रत्यक्ष
new A()
का उपयोग औरmy_new<A>()
पर कॉल वही स्थिति पर वस्तुतः होता है। तो यह कारण नहीं हो सकता है। सही? - अपूर्ण प्रकारों का उपयोग
template
के रूप में तर्क अपरिभाषित व्यवहार हो सकता है। क्या यह वास्तव में सच है? यहां तक कि सभी चेतावनियों को सक्षम करते समय, संकलक शिकायत नहीं करेगा। 5 और 6 की तुलना में यह भी सुझाव मिलता है कि संकलक यह समझने के लिए पर्याप्त स्मार्ट है कि परिभाषा नीचे दी गई है (इस प्रकार वस्तुतः प्रकार को पूरा कर रहा है)।
क्यों 4 को गलत माना जाता है, जबकि 5 संकलन (या 5 केवल उग्र रूप से अपरिभाषित व्यवहार को संकलित करते हैं [लेकिन फिर 3 को भी दोषपूर्ण होना चाहिए, है ना?))?
Btw: बजना साथ ++ का परीक्षण किया - 3.5.0 और जी ++ - 4.9.2
http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html – OmnipotentEntity
यदि यह अस्पष्ट है, क्योंकि वह लेख केवल दो चरण नाम लुकअप के कठोर पक्ष को संबोधित करता है, टेम्पलेट्स नाम कोड पर एक और पास तक तत्काल नहीं किया जाता है, यह पहले से ही हो चुका है और 'ए' की परिभाषा को पढ़ता है, यही कारण है कि यह संकलित करता है। – OmnipotentEntity
अनुवाद इकाई के अंत तक टेम्पलेट त्वरण में देरी करने के लिए यह एक आम कार्यान्वयन तकनीक है। आपका कोड खराब गठित है, कोई निदान आवश्यक नहीं है। –