2011-01-28 14 views
6

निम्नलिखित C++ 0x कोड में मैंने क्लोन सदस्य फ़ंक्शन (यदि यह मौजूद है) का उपयोग करके किसी ऑब्जेक्ट को क्लोन करने का प्रयास किया है और एक प्रतिलिपि कन्स्ट्रक्टर पर वापस गिर रहा है:बीमार सी ++ 0x कोड या कंपाइलर बग?

struct use_copy_ctor {}; 
struct prefer_clone_func : use_copy_ctor {}; 

template<class T> 
auto clone(T const* ptr, prefer_clone_func) 
-> decltype(ptr->clone()) 
{ return ptr->clone(); } 

template<class T> 
auto clone(T const* ptr, use_copy_ctor) 
-> decltype(new T(*ptr)) 
{ return new T(*ptr); } 

struct abc { 
    virtual ~abc() {} 
    virtual abc* clone() const =0; 
}; 

struct derived : abc 
{ 
    derived* clone() const { return new derived(*this); } 
}; 

int main() 
{ 
    derived d; 
    abc* p = &d; 
    abc* q = clone(p,prefer_clone_func()); 
    delete q; 
} 

विचार ऑटो का उपयोग करना है। ..-> टेम्पलेट तर्क कटौती (एसएफआईएनएई) के हिस्से के रूप में बीमार गठित अभिव्यक्तियों को बाहर निकालने के लिए decltype (expr) और आंशिक क्रमबद्ध wrt के माध्यम से क्लोन फ़ंक्शन टेम्पलेट्स के बीच संभावित अस्पष्टता को हल करने के लिए दूसरा समारोह पैरामीटर।

दुर्भाग्यवश, जीसीसी 4.5.1 इस प्रोग्राम को स्वीकार नहीं करता है:

test.cpp: In function 'int main()': 
test.cpp:28:39: error: cannot allocate an object of abstract type 
    'abc' 
test.cpp:14:12: note: because the following virtual functions are 
    pure within 'abc': 
test.cpp:16:16: note:  virtual abc* abc::clone() const 
test.cpp:28:39: error: cannot allocate an object of abstract type 
    'abc' 
test.cpp:14:12: note: since type 'abc' has pure virtual functions 

अब सवाल यह है कि क्या यह एक कंपाइलर बग है या क्या मुझे लगता है कि SFINAE यहां लागू होता है? मैं एक ठोस तर्क के साथ एक जवाब की सराहना करता हूं।

संपादित करें: यदि मैं decltype(new T(*ptr)) को T* में बदलता हूं तो कोड संकलित करता है क्योंकि ओवरलोड रिज़ॉल्यूशन इस मामले में पहले फ़ंक्शन टेम्पलेट को पसंद करता है। लेकिन यह समारोह घोषणा के हिस्से के रूप में अभिव्यक्ति रखने के उद्देश्य को हरा देता है। इसका उद्देश्य संकलक को त्रुटि के मामले में ओवरलोड रिज़ॉल्यूशन सेट से फ़ंक्शन को किक करना है।

+0

मैं संदर्भ द्वारा "चयन" तर्क लेता हूं, क्योंकि विरासत शामिल है। यह नहीं कि यह आपके मुद्दे को हल करेगा ... –

+0

@Matthieu: इस टैग को प्रेषण करने के लिए संदर्भ के लिए संदर्भ आवश्यक नहीं है। आंशिक ऑर्डरिंग ओवरलोड रिज़ॉल्यूशन नियम अभी भी लागू होता है। मैंने यह जांच नहीं की है कि यह संकलक द्वारा अनुकूलित कैसे किया जाता है लेकिन libstdC++ उदाहरण के लिए std :: अग्रिम को लागू करने के संदर्भों के बिना टैग प्रेषण का भी उपयोग करता है। – sellibitze

+0

मैं जानता हूँ कि यह आवश्यक नहीं है, मैं अभी भी यह आदत से बाहर करना होगा, मुझे लगता है, वस्तु टुकड़ा करने की क्रिया (कि एक टैग किसी भी डेटा/तरीकों के लिए ... माना जाता है नहीं) –

उत्तर

1

मुझे लगता है कि मैंने खुद को आश्वस्त किया कि यह वास्तव में एक कंपाइलर बग है और report दायर किया है। चलिए देखते हैं क्या होता है। एक कामकाज के रूप में decltype(new T(*ptr))T* के साथ प्रतिस्थापित किया जा सकता है। केवल अंतर यह है कि फ़ंक्शन टेम्पलेट ओवरलोड रिज़ॉल्यूशन सेट का हिस्सा रहेगा जो इस मामले में एक बड़ी समस्या नहीं है।

संपादित करें: बीटीडब्ल्यू, मुझे बताया गया था कि क्लैंग ++ उपरोक्त कोड स्वीकार करता है।

1

मैं MSVC के साथ एक बहुत समान समस्या थी, और यह पता चला कि संकलक आभासी समारोह में अपने सह-संस्करण वापसी प्रकार की पहचान नहीं होगा। abc लौटने के लिए क्लोन की derived की परिभाषा को बदलने का प्रयास करें।

+0

यह मदद नहीं करता है से बचने के लिए। 'व्युत्पन्न 'सार नहीं है। मैं मुख्य फ़ंक्शन में 'व्युत्पन्न' प्रकार का ऑब्जेक्ट भी बना सकता हूं। – sellibitze

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