2010-07-04 11 views
55

पर सी ++ टेम्पलेट पैरामीटर को प्रतिबंधित करें मैं एक विशिष्ट वर्ग Baseclass के उप-वर्ग होने के लिए टेम्पलेट पैरामीटर T को कैसे बल दूं? कुछ इस तरह:सबक्लास

template <class T : Baseclass> void function(){ 
    T *object = new T(); 

} 
+3

आप इसे करने के द्वारा क्या करने की कोशिश कर रहे हैं? – sth

+2

मैं बस यह सुनिश्चित करना चाहता हूं कि टी वास्तव में उप-वर्ग या कक्षा का एक उदाहरण है। मेरे द्वारा प्रदान किए गए फ़ंक्शन के अंदर कोड काफी अप्रासंगिक है। इसके विपरीत – phant0m

+6

, यह बहुत प्रासंगिक है। यह निर्धारित करता है कि यह एक अच्छा विचार है या उस परीक्षण में काम नहीं करना है। कई (सभी?) मामलों में, इस तरह की बाधाओं को स्वयं लागू करने की बिल्कुल आवश्यकता नहीं है, बल्कि संकलक होने पर संकलक इसे करने दें। उदाहरण के लिए, स्वीकृत उत्तर के लिए, 'बेसक्लास' से प्राप्त 'टी' पर जांच करना अच्छा होगा। अभी तक, यह जांच निहित है, और ओवरलोड रिज़ॉल्यूशन के लिए दृश्यमान नहीं है। लेकिन अगर कहीं भी ऐसी निहित बाधा नहीं होती है, तो कृत्रिम प्रतिबंध के लिए कोई कारण नहीं होता है। –

उत्तर

44

इस मामले में आप कर सकते हैं:

template <class T> void function(){ 
    Baseclass *object = new T(); 

} 

यह अगर टी Baseclass (या टी Baseclass है) के एक उपवर्ग नहीं है संकलन नहीं होंगे।

+0

आह हाँ, यह एक अच्छा विचार है। धन्यवाद! मैं इसे लेता हूं तो टेम्पलेट परिभाषा में इसे परिभाषित करने का कोई तरीका नहीं है? – phant0m

+2

@ phant0m: सही। आप स्पष्ट रूप से टेम्पलेट पैरामीटर को बाधित नहीं कर सकते हैं (अवधारणाओं को छोड़कर, जिन्हें सी ++ 0x के लिए माना जाता था लेकिन फिर गिरा दिया गया था)। सभी बाधाएं आपके द्वारा किए जाने वाले परिचालनों से पूरी तरह से होती हैं (या दूसरे शब्दों में केवल बाधा है "प्रकार को उस पर किए गए सभी कार्यों का समर्थन करना चाहिए")। – sepp2k

+1

एएचआईसी। स्पष्टीकरण के लिए बहुत बहुत धन्यवाद! – phant0m

0

बेस क्लास में मौजूद आपके टेम्पलेट के अंदर फ़ंक्शंस कॉल करके।

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

+2

यह सुनिश्चित नहीं करता है कि 'टी' * एक *' बेस क्लास 'है क्योंकि' बेस क्लास 'में घोषित सदस्यों को 'टी' की घोषणा में दोहराया जा सकता है। सुझाव के लिए –

5

आप इस्तेमाल कर सकते हैं Boost Concept Check के BOOST_CONCEPT_REQUIRES:

#include <boost/concept_check.hpp> 
#include <boost/concept/requires.hpp> 

template <class T> 
BOOST_CONCEPT_REQUIRES(
    ((boost::Convertible<T, BaseClass>)), 
(void)) function() 
{ 
    //... 
} 
+0

धन्यवाद। मैं इसकी जांच करुँगा। – phant0m

8

आप अवधारणाओं की जरूरत नहीं है, लेकिन आप उपयोग कर सकते हैं SFINAE:

template <typename T> 
boost::enable_if< boost::is_base_of<Base,T>::value >::type function() { 
    // This function will only be considered by the compiler if 
    // T actualy derived from Base 
} 

ध्यान दें कि यह समारोह का दृष्टांत जाएगा केवल जब हालत पूरा हो गया है, लेकिन अगर स्थिति पूरी नहीं हुई है तो यह एक समझदार त्रुटि प्रदान नहीं करेगा।

+0

क्या होगा यदि आप इस तरह के सभी कार्यों को लपेटें? बीटीडब्ल्यू यह क्या वापस करता है? –

+0

'enable_if' एक दूसरा प्रकार पैरामीटर लेता है जो' शून्य 'पर डिफ़ॉल्ट होता है। अभिव्यक्ति 'enable_if < true, int > :: प्रकार' प्रकार' int' का प्रतिनिधित्व करता है। मैं वास्तव में समझ नहीं पा रहा हूं कि आपका पहला सवाल क्या है, आप जो चाहें उसके लिए आप SFINAE का उपयोग कर सकते हैं, लेकिन मुझे समझ में नहीं आता कि आप सभी कार्यों के साथ क्या करना चाहते हैं। –

39

कार्यावधि में कम बेकार कोड निष्पादित करने के लिए आप देख सकते हैं: http://www.stroustrup.com/bs_faq2.html#constraints जो कुछ वर्गों है कि संकलन समय परीक्षण कुशलतापूर्वक प्रदर्शन प्रदान करता है, और अच्छे त्रुटि संदेश का उत्पादन।

विशेष रूप से:

template<class Derived> class MyClass { 

    MyClass() { 
     // Compile-time sanity check 
     static_assert(std::is_base_of<BaseClass, Derived>::value, "Derived not derived from BaseClass"); 

     // Do other construction related stuff... 
     ... 
    } 
} 

मैं जीसीसी 4.8.1 संकलक का उपयोग कर बाहर इस जाँच की है:

template<class T, class B> struct Derived_from { 
     static void constraints(T* p) { B* pb = p; } 
     Derived_from() { void(*p)(T*) = constraints; } 
}; 

template<class T> void function() { 
    Derived_from<T,Baseclass>(); 
} 
+1

लिंक के लिए धन्यवाद! – phant0m

+1

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

+1

वास्तव में, यह एक जवाब का नरक है! धन्यवाद। साइट उल्लेख यहां ले जाया जाता है: http://www.stroustrup.com/bs_faq2.html#constraints –

54
एक सी ++ 11 अनुरूप संकलक के साथ

, तो आप कुछ इस तरह कर सकते हैं एक CYGWIN पर्यावरण के अंदर - तो यह * निक्स वातावरण में भी काम करना चाहिए।

+0

मेरे लिए यह भी इस तरह काम करता है: 'टेम्पलेट <क्लास टेन्टीटी> क्लास बेसबीज़ { static_assert (std :: is_base_of <बेसइन्टिटी, टेन्टीटी> :: मान," बेसेंटीटी बेसटेन्टिटी से नहीं ली गई ");' –

+0

यह केवल तभी काम करता है जब पूरा टेम्पलेट हेडर में है। – peterh

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