निम्नलिखित 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*
में बदलता हूं तो कोड संकलित करता है क्योंकि ओवरलोड रिज़ॉल्यूशन इस मामले में पहले फ़ंक्शन टेम्पलेट को पसंद करता है। लेकिन यह समारोह घोषणा के हिस्से के रूप में अभिव्यक्ति रखने के उद्देश्य को हरा देता है। इसका उद्देश्य संकलक को त्रुटि के मामले में ओवरलोड रिज़ॉल्यूशन सेट से फ़ंक्शन को किक करना है।
मैं संदर्भ द्वारा "चयन" तर्क लेता हूं, क्योंकि विरासत शामिल है। यह नहीं कि यह आपके मुद्दे को हल करेगा ... –
@Matthieu: इस टैग को प्रेषण करने के लिए संदर्भ के लिए संदर्भ आवश्यक नहीं है। आंशिक ऑर्डरिंग ओवरलोड रिज़ॉल्यूशन नियम अभी भी लागू होता है। मैंने यह जांच नहीं की है कि यह संकलक द्वारा अनुकूलित कैसे किया जाता है लेकिन libstdC++ उदाहरण के लिए std :: अग्रिम को लागू करने के संदर्भों के बिना टैग प्रेषण का भी उपयोग करता है। – sellibitze
मैं जानता हूँ कि यह आवश्यक नहीं है, मैं अभी भी यह आदत से बाहर करना होगा, मुझे लगता है, वस्तु टुकड़ा करने की क्रिया (कि एक टैग किसी भी डेटा/तरीकों के लिए ... माना जाता है नहीं) –