2015-12-22 6 views
10

निम्नलिखित कोड में, wrapper<T> ऑब्जेक्ट घोषित किया गया है जिसमें movable<T> है, जहां T एक अपूर्ण प्रकार है। movable का विनाशक बनाया गया है ताकि इसे T के पूर्ण ज्ञान के बिना तत्काल नहीं किया जा सके, लेकिन wrapper का विनाशक केवल आगे घोषित किया गया है, जिसका अर्थ यह है कि ~movable()~wrapper() की परिभाषा के बिंदु पर तत्काल होना चाहिए।एक अस्वीकार्य कन्स्ट्रक्टर को विनाशक के तत्काल आवश्यकता क्यों होती है?

#include <utility> 

template<class T> 
struct movable { 
    movable() noexcept = default; 
    ~movable() noexcept { (void) sizeof(T); } 
    movable(const movable&) noexcept = delete; 
    movable(movable &&) noexcept = default; 
}; 

template<class T> 
class wrapper { 
public: 
    movable<T> m; 
    wrapper() noexcept = default; 
    wrapper(wrapper &&) noexcept = default; 
    ~wrapper(); 
}; 

struct incomplete; 

int main() { 
    /* extern */ wrapper<incomplete> original; 
    wrapper<incomplete> copy(std::move(original)); 
} 

(Try it here)

हालांकि, wrapper()~movable() का दृष्टांत करना चाहता है। मुझे लगता है कि अपवाद के मामले में, सदस्यों का विनाश संभव होना चाहिए, लेकिन movable() और wrapper() दोनों ही अस्वीकार्य हैं। दिलचस्प बात यह है कि चालक कन्स्ट्रक्टर ठीक काम करता है (उदाहरण कोड में extern भाग को असम्बद्ध करने का प्रयास करें।)

इस व्यवहार का कारण क्या है, और क्या इसे रोकने के लिए कोई तरीका है?

+1

बजना संकलन भी विफल रहता है। – interjay

+0

एचएम, "क्लास टेम्पलेट की पूर्णता प्रोग्राम के अर्थशास्त्र को प्रभावित कर सकती है, तो" एक क्लास टेम्पलेट तत्काल है "... हो सकता है कि इसके साथ कुछ करने के लिए कुछ हो? –

+0

यदि किसी वर्ग में कई सदस्य होते हैं, और निर्माण के दौरान प्रारंभिकरणों में से एक फेंकता है, तो पहले पूर्ण प्रारंभिक प्रारंभिक सदस्यों को संबंधित सदस्यों के विनाशकों को बुलाकर पूर्ववत करना होगा। मुझे लगता है कि आप जो देखते हैं उससे संबंधित है। – dyp

उत्तर

4

द्वारा टीसी मनाया के रूप में,

एक गैर सौंपने के निर्माता में, के लिए [...] वर्ग प्रकार से प्रत्येक गैर स्थैतिक डेटा सदस्य संभावित शुरू हो जाती है [...]

नाशक

प्रति DR1424, प्रेरणा यह स्पष्ट करना है कि अगर कोई विनाशक मूल वस्तु के निर्माता से पहुंच योग्य नहीं है, तो एक त्रुटि जारी करने के लिए एक कार्यान्वयन की आवश्यकता है, "[यहां तक ​​कि] अपवाद के अपवाद की कोई संभावना नहीं है दिए गए उप-ऑब्जेक्ट के निर्माण के बाद "।

movable<T> का नाशक पहुँचा जा सकता है, लेकिन यह instantiated नहीं किया जा सकता है, जो वह जगह है जहाँ आपकी समस्या पैदा होती है के रूप में एक संभावित लागू नाशक है ओडीआर रूप से प्रयुक्त

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

एक ही रास्ता नाशक के संभावित मंगलाचरण से बचने नियुक्ति नई उपयोग करने के लिए हो सकता है, subobject खुद के जीवनकाल का प्रबंधन अपने हाथ लेने के लिए: जब `extern` uncommenting

#include <new> 
// ... 
template<class T> 
class wrapper { 
public: 
    std::aligned_storage_t<sizeof(movable<T>), alignof(movable<T>)> m; 
    wrapper() noexcept { new (&m) movable<T>; }; 
    wrapper(wrapper&& rhs) noexcept { new (&m) movable<T>{reinterpret_cast<movable<T>&&>(rhs.m)}; } 
    ~wrapper(); 
}; 
संबंधित मुद्दे

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