सी ++ covariant टेम्पलेट्स

वोट
16

मुझे लगता है कि यह एक से पहले कहा गया है, लेकिन मैं इतने पर पता नहीं लगा पा रहा हूँ, न ही मैं कुछ भी गूगल पर उपयोगी पा सकते हैं। शायद covariant शब्द मैं तलाश कर रहा हूँ नहीं है, लेकिन इस अवधारणा को बहुत कार्यों पर वापसी प्रकार covariant के समान है, इसलिए मुझे लगता है यह शायद सही है। यहाँ मुझे क्या करना चाहते हैं और यह मुझे एक संकलक त्रुटि देता है:

class Base;
class Derived : public Base;

SmartPtr<Derived> d = new Derived;
SmartPtr<Base> b = d; // compiler error

मान लें उन वर्गों पूरी तरह से बाहर fleshed कर रहे हैं ... मैं तुम्हें अंदाजा हो लगता है। यह एक परिवर्तित नहीं कर सकते SmartPtr<Derived>एक में SmartPtr<Base>कुछ स्पष्ट नहीं कारण के लिए। मुझे याद है कि इस है, हालांकि इस समय मैं क्यों याद नहीं कर सकते सी ++ और कई अन्य भाषाओं में सामान्य है।

मेरे जड़ सवाल यह है: क्या यह काम कार्रवाई करने के लिए सबसे अच्छा तरीका है? वर्तमान में, मैं से बाहर सूचक खींच कर रहा हूँ SmartPtr, स्पष्ट रूप से आधार प्रकार के लिए यह upcasting, फिर एक नया में यह लपेटकर SmartPtrउपयुक्त प्रकार के (ध्यान दें कि इस संसाधन लीक नहीं है, क्योंकि हमारे देसी SmartPtrवर्ग घुसपैठ संदर्भ गिनती का उपयोग करता है)। यही कारण है कि लंबी और गन्दा है, खासकर जब मैं तो रैप करने के लिए की जरूरत है SmartPtrअभी तक एक और वस्तु में ... किसी भी शॉर्टकट?

12/03/2009 को 16:46
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


6 जवाब

वोट
15

SmartPtr<Base>और SmartPtr<Derived>एक के दो अलग instantiations हैं SmartPtrटेम्पलेट। इन नए वर्गों विरासत का हिस्सा नहीं है कि Baseऔर Derivedसे करते हैं। इसलिए, आपकी समस्या।

क्या इस असाइनमेंट कार्रवाई करने के लिए सबसे अच्छा तरीका है?

 SmartPtr<Base> b = d; 

असाइनमेंट ऑपरेटर आह्वान नहीं करता है। यह कॉपी-ctor का आह्वान (कॉपी ज्यादातर मामलों में elided है) और वास्तव में है के रूप में यदि आप ने लिखा है:

 SmartPtr<Base> b(d); 

एक कॉपी-ctor कि एक लेता है के लिए प्रदान करें SmartPtr<OtherType>और इसे लागू। एक ही असाइनमेंट ऑपरेटर के लिए चला जाता है। आप = कॉपी-ctor और सेशन को लिखने के लिए होगा मन में SmartPtr के शब्दों रखते हुए।

12/03/2009 को 16:57
का स्रोत उपयोगकर्ता

वोट
11

दोनों प्रतिलिपि निर्माता और असाइनमेंट ऑपरेटर एक अलग प्रकार का एक SmartPtr लेने के लिए और अन्य एक से सूचक कॉपी करने के लिए प्रयास करने के लिए सक्षम होना चाहिए। प्रकार के संगत नहीं हैं, तो संकलक शिकायत, और अगर वे संगत कर रहे हैं, आप अपनी समस्या को हल कर दिया है। कुछ इस तरह:

template<class Type> class SmartPtr
{
    ....
    template<class OtherType> SmartPtr(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> copy constructor

    template<class OtherType> SmartPtr<Type> &operator=(const SmartPtr<OtherType> &blah) // same logic as the SmartPtr<Type> assignment operator
};
12/03/2009 को 16:56
का स्रोत उपयोगकर्ता

वोट
5

टेम्पलेट्स covariant नहीं हैं, और यह अच्छी बात है; कल्पना क्या निम्नलिखित मामले में क्या होगा:

vector<Apple*> va;
va.push_back(new Apple);

// Now, if templates were covariants, a vector<Apple*> could be
// cast to a vector<Fruit*>
vector<Fruit*> & vf = va;
vf.push_back(new Orange); // Bam, we just added an Orange among the Apples!

प्राप्त करने के लिए आपको बस इतना करना कोशिश कर रहे हैं, SmartPointer वर्ग एक templatized निर्माता, है कि या तो एक और SmartPointer या किसी अन्य प्रकार का एक सूचक लेता होना आवश्यक है। आप को बढ़ावा देने :: shared_ptr है, जो वास्तव में करता है पर एक नज़र हो सकता था।

template <typename T>
class SmartPointer {

    T * ptr;

  public:
    SmartPointer(T * p) : ptr(p) {}
    SmartPointer(const SmartPointer & sp) : ptr(sp.ptr) {}

    template <typename U>
    SmartPointer(U * p) : ptr(p) {}

    template <typename U>
    SmartPointer(const SmartPointer<U> & sp) : ptr(sp.ptr) {}

    // Do the same for operator= (even though it's not used in your example)
};
12/03/2009 को 17:02
का स्रोत उपयोगकर्ता

वोट
3

पर निर्भर करता है SmartPtrवर्ग। यदि यह एक प्रतिलिपि निर्माता है (या अपने मामले, असाइनमेंट ऑपरेटर में) है कि लेता है SmartPtr<T>, जहां टी प्रकार इसके साथ, तो यह काम करने के लिए नहीं जा रहा है निर्माण किया गया था है, क्योंकि SmartPtr<T1>कोई संबंध नहीं है करने के लिए SmartPtr<T2>टी 1 और टी 2 विरासत से संबंधित हैं, भले ही ।

हालांकि, अगर SmartPtr एक है templatized प्रतिलिपि निर्माता / असाइनमेंट ऑपरेटर, टेम्पलेट पैरामीटर के साथ TOther, कि स्वीकार करता है SmartPtr<TOther>, तो यह काम करना चाहिए।

12/03/2009 को 16:56
का स्रोत उपयोगकर्ता

वोट
2

मान लें कि आप SmartPtr वर्ग के नियंत्रण है, समाधान एक टेम्प्लेट की निर्माता प्रदान करना है:

template <class T>
class SmartPtr
{
    T *ptr;
public:

    // Note that this IS NOT a copy constructor, just another constructor that takes 
    // a similar looking class.
    template <class O>
    SmartPtr(const SmartPtr<O> &src)
    {
        ptr = src.GetPtr();
    }
    // And likewise with assignment operator.
};

टी और ओ प्रकार के संगत हैं, यह काम करेंगे, अगर वे कर रहे हैं आप एक संकलन त्रुटि नहीं मिलेगा।

12/03/2009 को 16:56
का स्रोत उपयोगकर्ता

वोट
0

मुझे लगता है कि सबसे आसान काम निम्नलिखित के अनुसार एक और SmartPtr के लिए स्वत: रूपांतरण प्रदान करना है:

template <class T>
class SmartPtr
{
public:
    SmartPtr(T *ptr) { t = ptr; }
    operator T * () const { return t; }
    template <class Q> operator SmartPtr<Q> () const
    { return SmartPtr<Q>(static_cast<Q *>(static_cast<T *>(* this))); }
private:
    T *t;
};

ध्यान दें कि इस कार्यान्वयन अर्थ में मजबूत है कि रूपांतरण ऑपरेटर टेम्पलेट स्मार्ट सूचक के शब्दों के बारे में पता करने की जरूरत नहीं है कि, तो संदर्भ गिनती दोहराया करने आदि की जरूरत नहीं है

12/03/2009 को 18:26
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more