2010-02-15 9 views
24

मेरे टेम्पलेट-ized फ़ंक्शन में, मैं टाइप टी को एक विशिष्ट प्रकार की जांच करने की कोशिश कर रहा हूं। मुझे यह कैसे करना है?मैं अपनी टेम्पलेट क्लास को एक विशिष्ट क्लैस्स्टइप की जांच कैसे करूं?

पी/एस मुझे टेम्पलेट विनिर्देशन तरीका पता था लेकिन मैं ऐसा नहीं करना चाहता।

template<class T> int foo(T a) { 
    // check if T of type, say, String? 
} 

धन्यवाद!

+3

क्यों नहीं करते आप "टेम्पलेट विनिर्देश रास्ता चाहते हैं "? –

+3

"टेम्पलेट ओवरलोडिंग तरीका" का उपयोग करें :) –

+0

आपको शायद व्यवहार की जांच करनी चाहिए, टाइप न करें। – MSalters

उत्तर

7

मैं तुम्हें std::type_info typeid ऑपरेटर

+0

मुझे लगता है कि मुझे यही चाहिए। आपका बहुत बहुत धन्यवाद! – huy

+7

चेतावनी: रनटाइम चेक का प्रयास करें। इस प्रकार, आप संकलन-समय गुणों पर भरोसा नहीं कर सकते हैं। जैसे टी == std :: स्ट्रिंग की जांच करने के बाद आप 'ऑपरेटर []' का उपयोग नहीं कर सकते हैं। – MSalters

+1

@huy आमतौर पर रनटाइम चेक के बजाए प्रकारों के लिए स्थिर जांच करना बेहतर होता है। इस प्रकार, 'std :: is_same',' std :: is_convertible', या समान है। फिर आप प्रकार की जांच करने की रनटाइम लागत से बच सकते हैं। इसके बजाय, अगर आपके कोड का केवल एक हिस्सा इस प्रकार को जानना आवश्यक है, तो 'if constexpr' (C++ 17) या एक सहायक फ़ंक्शन का उपयोग करें; यदि आपका सभी कोड करता है, तो फ़ंक्शन ओवरलोडिंग का उपयोग करें। –

48

प्रकार के उपयोग विशेषज्ञता के लिए जांच करने के बजाय। अन्यथा, टेम्पलेट का उपयोग न करें।

template<class T> int foo(T a) { 
     // generic implementation 
} 
template<> int foo(SpecialType a) { 
    // will be selected by compiler 
} 

SpecialType x; 
OtherType y; 
foo(x); // calls second, specialized version 
foo(y); // calls generic version 
+0

फ़ंक्शन टेम्पलेट्स को विशेषज्ञ बनाना अक्सर एक बुरा विचार है; आंशिक विशेषज्ञता समर्थित नहीं है, और यदि आप विशेषज्ञता और अधिभार को मिलाते हैं तो आपको अक्सर अप्रत्याशित परिणाम मिलते हैं। शुरुआत से बस अधिभार। –

4

आप type_traits (available in Boost and TR1) (जैसे is_same या is_convertible) का उपयोग करता है, तो क्या तुम सच में विशेषज्ञता से बचना चाहते हैं देख सकते हैं।

+0

बेशक एस/से बचें/छुपाएं/ – MSalters

12

द्वारा लौटाए का उपयोग आप के बारे में संकलन समय परवाह नहीं है, तो हो सकता है, तो आप boost::is_same उपयोग कर सकते हैं लगता है। (बढ़ावा प्रकार लक्षण पुस्तकालय को देखने)

bool isString = boost::is_same<T, std::string>::value; 

सी ++ 11 के रूप में, यह अब मानक पुस्तकालय

bool isString = std::is_same<T, std::string>::value 
+4

रिकॉर्ड के लिए: [is_same] (http://en.cppreference.com/w/cpp/types/is_same) अब मानक लाइब्रेरी का हिस्सा है। – kebs

2

आप प्रकार है कि आप प्राप्त हुआ है पर स्थिर जांच कर सकते हैं का हिस्सा है , लेकिन जब तक आप एक बिंदु या दूसरे पर विशेषज्ञता (या ओवरलोड, @litb सही ढंग से इंगित करते हैं) का उपयोग नहीं करते हैं, तो आप तर्क प्रकार के आधार पर अलग-अलग विशिष्ट कार्यान्वयन प्रदान नहीं कर पाएंगे।

जब तक आपके पास कोई विशेष कारण नहीं है (जिसे आप प्रश्न में जोड़ सकते हैं) इंटरफ़ेस में विशेषज्ञता का उपयोग न करने के लिए बस विशेषज्ञ करें।

template <> int subtract( std::string const & str); 
6

मुझे लगता है कोई आपको बता क्यों यह एक अच्छा विचार नहीं हो सकता है अधिक भार या विशेषज्ञता का उपयोग नहीं करना चाहिए। पर विचार करें:

template<class T> int foo(T a) { 
    if(isAString<T>()) { 
    return a.length(); 
    } else { 
    return a; 
    } 
} 

आप एक पहली नजर है कि यह भी int के लिए काम करेंगे क्योंकि यह केवल तार के लिए length फोन करने की कोशिश करेंगे पर सोच सकते हैं। लेकिन वह अंतर्ज्ञान गलत है: संकलक अभी भी स्ट्रिंग शाखा की जांच करता है, भले ही वह शाखा रनटाइम पर नहीं ली जाती है। और यदि आप T एक int है तो आप पाएंगे कि आप गैर-वर्गों पर सदस्य फ़ंक्शन को कॉल करने का प्रयास कर रहे हैं।

यही कारण है कि यदि आपको अलग-अलग व्यवहार की आवश्यकता है तो आपको कोड को अलग करना चाहिए। लेकिन विशेषज्ञता के बजाए ओवरलोडिंग का बेहतर उपयोग करें, क्योंकि यह समझना आसान है कि चीजें इसके साथ कैसे काम करती हैं।

template<class T> int foo(T a) { 
    return a; 
} 

int foo(std::string const& a) { 
    return a.length(); 
} 

आपने व्यवहार के विभिन्न तरीकों के लिए भी कोड को अलग किया है। यह सब अब एक साथ चिपकाया नहीं है। ध्यान दें कि ओवरलोडिंग के साथ, पैरामीटर में अलग-अलग प्रकार के रूप हो सकते हैं और कंपाइलर अभी भी सही संस्करण का उपयोग करेगा यदि दोनों समान मिलान करते हैं, जैसा कि यहां है: कोई संदर्भ हो सकता है, जबकि दूसरा नहीं कर सकता है।

+0

मुझे आपके द्वारा पहले बताए गए मुद्दे का सामना करना पड़ा, इसलिए मैं ठीक करने का कोई तरीका नहीं ढूंढना चाहता था, लेकिन अधिभार या कक्षा विशेषज्ञता के बिना। मैंने 'सुराग प्राप्त करने के लिए चीजें कैसे काम करेंगे' के बारे में नहीं सोचा था। इसे पुनर्विचार करेंगे, धन्यवाद! – huy

+0

@ हू, आपका स्वागत है। –

+0

एक कलाकार के साथ अपना उदाहरण संशोधित करना चाल करेगा। लेकिन यह अभी भी मेरा पसंदीदा समाधान नहीं होगा :) –

9

हम्म क्योंकि मैं 'विनिर्देश' हिस्सा जब तक एक ही कोड का एक बड़ा हिस्सा था।

आप अधिक भार का उपयोग कर सकते हैं, लेकिन अगर कोड का एक बड़ा हिस्सा किसी भी प्रकार के लिए काम करेंगे, तो आपको एक अलग समारोह में अलग-अलग हिस्सा निकालने पर विचार करने और ओवरलोड कि हो सकता है।

template <class T> 
void specific(const T&); 

void specific(const std::string&); 

template <class T> 
void something(const T& t) 
{ 
    //code that works on all types 
    specific(t); 
    //more code that works on all types 
} 
+0

के लिए है, तो बहुत आसान समाधान, इस उत्तर के लिए धन्यवाद! – avtomaton

0

आप सी ++ 11 या बाद में, उपयोग कर रहे हैं std :: is_same बिल्कुल वही करती आप क्या चाहते हैं:

template <typename T> 
constexpr bool IsFloat() { return std::is_same<T, float>::value; } 

template <typename T> 
void SomeMethodName() { 
    if (IsFloat<T>()) { 
    ... 
    } 
} 

http://en.cppreference.com/w/cpp/types/is_same

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