2010-03-16 12 views
12

मेरे पास मूल टेम्पलेट क्लास है, लेकिन मैं कक्षाओं या प्रकारों के सेट पर विशेषज्ञता के प्रकार को रोकना चाहता हूं। उदाहरण:फोर्स प्रकार का सी ++ टेम्पलेट

template <typename T> 
class MyClass 
{ 
.../... 
private: 
    T* _p; 
}; 

MyClass<std::string> a; // OK 
MYCLass<short> b;  // OK 
MyClass<double> c;  // not OK 

ये केवल उदाहरण हैं, स्वीकृत प्रकार भिन्न हो सकते हैं।

क्या यह भी संभव है? यदि ऐसा है, तो ऐसा कैसे करें?

धन्यवाद।

+1

मैं उत्सुक हूँ के लिए अपरिभाषित छोड़ने के लिए है, जो उपयोग के मामले आप अपने टेम्पलेट के कुछ इन्स्टेन्शियशन मना के लिए क्या है? मैं यह नहीं समझ सकता कि मैं अपने कोड का पुन: उपयोग क्यों नहीं करना चाहूंगा: -/ – Seb

+0

"भिन्न हो सकता है" का क्या अर्थ है? क्या वे संकलन समय में भिन्न हो सकते हैं या उदाहरण के मुकाबले अलग हो सकते हैं? – foraidt

+3

@ सेब: टेम्पलेट कुछ प्रकार के साथ सही ढंग से काम नहीं कर सकता है। यह संकलित नहीं हो सकता है (जिस स्थिति में कंपाइलर जो कुछ भी उत्पन्न करता है उससे क्लीनर त्रुटि संदेश वांछनीय हो सकता है), या यह संकलित हो सकता है लेकिन वांछित अर्थशास्त्र नहीं है (जिस स्थिति में इसे संकलन से रोकने के लिए एक तरीका अच्छा है) – jalf

उत्तर

17

एक और संस्करण यह वर्जित प्रकार

template<typename T> 
struct Allowed; // undefined for bad types! 

template<> struct Allowed<std::string> { }; 
template<> struct Allowed<short> { }; 

template<typename T> 
struct MyClass : private Allowed<T> { 
    // ... 
}; 

MyClass<double> m; // nono 
+2

+1। वास्तव में, मुझे इस समाधान को पहले जवाब से बेहतर पसंद है। – paercebal

+0

@paercebal, धन्यवाद साथी xD –

+0

आपका स्वागत है। वैसे भी, मेरी आखिरी टिप्पणी के बाद, आपका उत्तर चयनित उत्तर बन गया, इसलिए जाहिर है, मैं अपने मूल्यों को देखने वाला अकेला नहीं हूं ... :-P – paercebal

1

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

template <typename T> struct protector { 
static const int result = 1; 
}; 

template <> struct protector<double> { 
static const int result = -1; 
}; 

template <typename T> 
class MyClass 
{ 
    private: 
    char isfine[protector<T>::result]; 
}; 

यह बेहतर हो सकता है, हालांकि, अपने कोड पर एक वसा टिप्पणी डालने के लिए उपयोगकर्ताओं को गलत प्रकार के साथ instantiating से रखने के लिए:

8

yust एक त्वरित विचार है, मैं कर रहा हूँ यकीन है कि वहाँ बेहतर तरीके हैं: -)

+0

आप हराते हैं मुझे इसके लिए यहां इस्तेमाल किया जाने वाला मुहावरे * प्रकार के लक्षण * कहा जाता है। –

+4

क्या हर उदाहरण में char [1] सरणी की लागत के बिना ऐसा करने का कोई और तरीका है? व्यक्तिगत रूप से, मैं BOOST_STATIC_ASSERT का उपयोग करता हूं। –

+2

'char' से पहले' typedef' जोड़ें। – Ari

1

इम इस बारे में निश्चित नहीं हैं, लेकिन आप डबल टेम्पलेट

class MyClass 
{ 
.../... 
private: 
    T* _p; 
}; 

template <double> class MyClass 
{}; 

जो आप के लिए काम करेंगे के लिए एक और टेम्पलेट विशेषज्ञता जोड़ सकता है उदाहरण के लिए, लेकिन सामान्य मामले के लिए नहीं।

सामान्य रूप से, मैं अवांछित प्रकारों की जांच के लिए एक संकलित जोर जोड़ता हूं।

उम्मीद है कि यह मदद करता है।

2

आम तौर पर यह प्रतिबंधित करने के लिए अनावश्यक है कि किस प्रकार के टेम्पलेट्स को तुरंत चालू किया जा सकता है। या तो टेम्पलेट दिए गए प्रकार (और ठीक काम करता है) के साथ संकलित है या यह नहीं है (और प्रोग्रामर के हिस्से पर किसी भी प्रयास के बिना एक कंपाइलर त्रुटि उत्पन्न करता है)।


आप प्रतिबंध में डालने के लिए की जरूरत है, आम तौर पर प्रकार आम में कुछ कुछ प्रकार के लक्षण है कि पहले से ही उपलब्ध हैं (मानक पुस्तकालय, boost::type_traits) द्वारा वर्णित किया जा सकता है कि है, या आप के लिए एक नए प्रकार विशेषता बना सकते हैं उन्हें।

उदाहरण के लिए, यहां एक टेम्पलेट क्लास है जो इसे देखने के लिए std::numeric_limits का उपयोग करके पूर्णांक प्रकारों की अनुमति देता है (यदि आप अपना स्वयं का अंकीय प्रकार लिखते हैं, तो आप इसे विशेषज्ञ कर सकते हैं ताकि यह आपके नए पूर्णांक प्रकार के साथ भी काम करे)। static_assert केवल सी ++ 0x है, अगर उपलब्ध नहीं है तो BOOST_STATIC_ASSERT या कुछ अन्य चाल का उपयोग करें।

#include <limits> 
#include <string> 

template <class T> 
class X 
{ 
    static_assert(std::numeric_limits<T>::is_integer, "X can be only instantiated with integer types"); 
    //... 
}; 

int main() 
{ 
    X<int> xi; 
    X<char> xc; 
    //X<double> xd; 
    //X<std::string> xs; 
} 

आप केवल आम में कुछ भी नहीं के साथ मनमाना प्रकार के एक मुट्ठी भर का समर्थन करने के (के रूप में अपने काल्पनिक उदाहरण से स्पष्ट है) की योजना है, एक तरह से typelists को रोजगार के लिए है। फिर से बढ़ावा देने से कार्य बहुत आसान हो सकता है, लेकिन यहां बताया गया है कि आप अपना खुद का रोल कैसे कर सकते हैं (यह केवल आधा रास्ता जाता है, टाइपलिस्टिस्ट सुंदर को घोषित करने के लिए अतिरिक्त काम की आवश्यकता होगी)।

struct no_type {}; 

template <class T, class U = no_type> 
struct t_list 
{ 
    typedef T head; 
    typedef U tail; 
}; 

//trait to check if two types are identical 
template <class T, class U> 
struct is_same 
{ 
    static const bool value = false; 
}; 

template <class T> 
struct is_same<T, T> 
{ 
    static const bool value = true; 
}; 

//compile-time recursion to check if T matches any type in list L 
template <class T, class L> 
struct in_type_list 
{ 
    static const bool value = 
     is_same<T, typename L::head>::value || in_type_list<T, typename L::tail>::value; 
}; 

//terminates recursion 
template <class T> 
struct in_type_list<T, no_type> 
{ 
    static const bool value = false; 
}; 

template <class T> 
class X 
{ 
    typedef t_list<double, t_list<int, t_list<char> > > allowed_types; //double, int, char 

    //poor man's static_assert 
    typedef int check_type [in_type_list<T, allowed_types>::value ? 1 : -1]; 
    //... 
}; 

int main() 
{ 
    X<char> xc; 
    X<int> xi; 
    X<double> xd; 
    //X<float> xf; 
} 
संबंधित मुद्दे