2014-05-19 8 views
9

यह प्रश्न टेम्पलेट कक्षाओं के स्पष्ट instanciation पर विचार कर रहा है।आधार टेम्पलेट कक्षाओं को स्पष्ट रूप से कैसे स्थापित करें?

किसी अन्य टेम्पलेट वर्ग A<T> से प्राप्त टेम्पलेट क्लास B<T> पर विचार करें। मैं B<T> को स्पष्ट रूप से instanicate करना चाहता हूं क्योंकि इसकी विधियों को गतिशील लिंकिंग से बुलाया जाना है, इसलिए विधियों को तत्काल किया जाना चाहिए हालांकि उन्हें कोड में स्वयं नहीं कहा जाता है। बेशक, A<T> से विरासत में प्राप्त विधियों को भी बुलाया जाएगा, इसलिए उन्हें भी कम किया जाना चाहिए।

ऐसा लगता है कि सी ++ के रूप में इस प्रश्न में पूछा नहीं instanciate आधार वर्ग जब स्पष्ट रूप से एक टेम्पलेट वर्ग instanciating करता है,: Do Explicit Instantiations of C++ Class Templates Instantiate Dependent Base Classes? उदाहरण:

template<typename T> 
class A{ void foo(){...} }; 

template<typename T> 
class B : public A<T> {} 

template class B<int>; // This will NOT instanciate A<int>::foo()!!! 

बेशक, मैं भी सभी आधार वर्ग instanciate की जरूरत है। हालांकि, मैं इसके साथ क्लाइंट कोड को बोझ नहीं करना चाहता क्योंकि कक्षा पदानुक्रम बहुत गहरा हो सकता है। 10 या अधिक टेम्पलेट कक्षाओं को शामिल करने वाले वर्ग पदानुक्रम पर विचार करें। ग्राहक को 10 स्पष्ट टेम्पलेट instanciations लिखने के लिए आग्रह नहीं किया जाना चाहिए। यह केवल लेखन का बहुत कुछ नहीं है; जब मैं कक्षा पदानुक्रम में परिवर्तन पेश करता हूं तो यह भी टूट जाएगा।

इसके बजाय, मैं किसी भी तरह से हासिल करना चाहता हूं कि जब भी B<T> तत्काल हो, तो उसके सभी मूल वर्ग भी हैं। मैंने बी में बेस क्लास को बस इस तरह से स्थापित करने की कोशिश की:

template<typename T> 
class B : public A<T> { 
    template class A<T>; // Does not compile! 
} 

लेकिन यह संकलित नहीं होता है। क्या ऐसे अन्य तरीके हैं जो इसे प्राप्त कर सकते हैं?

उत्तर

2

शायद सुरुचिपूर्ण लेकिन कम से कम व्यावहारिक नहीं: टेम्पलेट का दृष्टांत के लिए एक मैक्रो प्रदान करते हैं और मैनुअल इन्स्टेन्शियशन की जगह में मैक्रो का उपयोग करने के लिए उपयोगकर्ता की आवश्यकता होती है:

// in A.hpp 
#define INSTANTIATE_A(T) template class A<T>; 

// in B.hpp 
#define INSTANTIATE_B(T) \ 
    INSTANTIATE_A(T)  \ 
    template class B<T>; 

और अगर आप पसंद करते हैं वर्ग इंटरफेस "प्रदूषण" एक तात्कालिकता मैक्रो के उपयोग को लागू करने के लिए: protected सदस्य जोड़ें जो टेम्पलेट के सभी अन्य सदस्य कार्यों और बेस क्लास में संस्करण को कॉल करता है। उदाहरण:

template<typename T> 
class A 
{ 
    void foo() {...} 
protected: 
    void instantiate() { foo(); } 
}; 

template<typename T> 
class B : public A<T> 
{ 
    void bar() {...} 
protected: 
    void instantiate() { A<T>::instantiate(); bar(); } 
}; 

template class B<int>; // Now works as expected 

अद्यतन: दूसरा समाधान करने के लिए

वैकल्पिक: सभी सदस्यों के समारोह सूचक लेते हैं और उन्हें एक अस्थायी चर को बचाने के लिए:

template<typename T> 
class A 
{ 
    void foo() {...} 
protected: 
    void instantiate() { void (A::*p)() = &A::foo; } 
}; 

template<typename T> 
class B : public A<T> 
{ 
    void bar() {...} 
protected: 
    void instantiate() { A<T>::instantiate(); void (B::*p)() = &B::foo; } 
}; 
+0

दूसरा समाधान के साथ समस्या यह है कि कुछ तरीकों में बड़े हस्ताक्षर होते हैं और विधियों को खिलाने के लिए मूल्यों का उत्पादन करना आसान नहीं होता है। पहला काम करेगा लेकिन वास्तव में बदसूरत है :( – gexicide

+0

दूसरे समाधान का एक संस्करण जोड़ा गया है, भले ही यह वर्बोज़ के बारे में है और वास्तव में आवश्यक नहीं है: विचार यह है कि 'तत्काल()' वास्तव में कभी निष्पादित नहीं होता है। –

+0

ठीक है, अधिक व्यवहार्य है। लेकिन फिर भी, इंटरफेस बड़े हैं, इसलिए सभी विधियों की गणना करना सभी आधार वर्गों की गणना करने से कहीं अधिक काम है। मुझे उम्मीद है कि इसमें से अन्य तरीके भी हैं, लेकिन इस जवाब के लिए धन्यवाद। – gexicide

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