टेम्पलेट पैरामीटर के प्रकार की जांच कैसे करें?


97

मान लीजिए मेरे पास एक टेम्पलेट फ़ंक्शन और दो कक्षाएं हैं

class animal {
}
class person {
}

template<class T>
void foo() {
  if (T is animal) {
    kill();
  }
}

टी के लिए मैं कैसे जांच कर सकता हूं पशु है? मैं कुछ ऐसा नहीं करना चाहता जो रन टाइम के दौरान चेक करे। धन्यवाद


61
मैं "मार" के बजाय "पालतू"
डालूंगा

जवाबों:


135

उपयोग करें is_same:

#include <type_traits>

template <typename T>
void foo()
{
    if (std::is_same<T, animal>::value) { /* ... */ }  // optimizable...
}

आमतौर पर, यह एक पूरी तरह से काम करने योग्य डिजाइन है, हालांकि, और आप वास्तव में विशेषज्ञ बनना चाहते हैं :

template <typename T> void foo() { /* generic implementation  */ }

template <> void foo<animal>()   { /* specific for T = animal */ }

ध्यान दें कि स्पष्ट (गैर-कटौती किए गए) तर्कों के साथ फ़ंक्शन टेम्प्लेट होना असामान्य है। यह अनसुना नहीं है, लेकिन अक्सर बेहतर दृष्टिकोण होते हैं।


2
TThanks! वास्तव में वे एक बहुत कोड साझा करते हैं, इसलिए मैं वास्तव में इसे डुप्लिकेट नहीं कर सकता हूं
व्हाट्सएपफुलवर्ल्ड वर्ल्ड

3
@WhatABeautifulWorld: आप हमेशा अपने कोड कारक बन सकते हैं ताकि प्रकार पर निर्भर हिस्सा एक specializable समारोह की चपेट में आ जा सकता है ...
Kerrek एस.बी.

1
एक त्वरित अनुवर्ती, अगर मैं std :: is_same का उपयोग करता हूं, तो यह अन्य टेम्पलेट मापदंडों के लिए कोड को धीमा नहीं करेगा, है ना?
व्हाट्सएपफुलफुलवर्ल्ड

1
@HatABeautifulWorld: विशेषता मान सभी सांख्यिकीय रूप से ज्ञात हैं। कोई रनटाइम लागत नहीं होनी चाहिए, बशर्ते आपका कंपाइलर आधा सभ्य हो। यदि संदेह है, तो विधानसभा की जाँच करें।
केरेक एसबी

2
@ AdriC.S .: चूंकि कटौती Tनहीं की गई है, इसलिए बहुत कुछ नहीं है जो आप कर सकते हैं। आप प्राथमिक टेम्पलेट को अनइम्प्लीमेंट करके छोड़ सकते हैं और एक विशेषज्ञता बना सकते हैं, या आप के साथ एक स्थैतिक अभिकथन जोड़ सकते हैं is_same
केरेक एसबी

37

मुझे लगता है कि आज, यह उपयोग करने के लिए बेहतर है, लेकिन केवल C ++ 17 के साथ।

#include <type_traits>

template <typename T>
void foo() {
    if constexpr (std::is_same_v<T, animal>) {
        // use type specific operations... 
    } 
}

यदि आप बिना अभिव्यक्ति शरीर में कुछ प्रकार के विशिष्ट संचालन का उपयोग करते हैं constexpr, तो यह कोड संकलित नहीं करेगा।


8
इसके बजाय std::is_same<T, U>::valueआप कम इस्तेमाल कर सकते हैं:std::is_same_v<T, U>
Fureeish

12

C ++ 17 में, हम उपयोग कर सकते हैं वेरिएंट का

काम में लाना std::variant , आपको शीर्ष लेख को शामिल करना होगा:

#include <variant>

उसके बाद, आप std::variantअपने कोड को इस तरह जोड़ सकते हैं :

using Type = std::variant<Animal, Person>;

template <class T>
void foo(Type type) {
    if (std::is_same_v<type, Animal>) {
        // Do stuff...
    } else {
        // Do stuff...
    }
}

8
टी और टाइप कैसे जुड़े हैं?
mabraham

4
यह उत्तर कई मायनों में समस्याग्रस्त है। वास्तविक त्रुटियों के अलावा ( typeजो प्रकार का मूल्य है Typeया एक टेम्पलेट जो यहां समझ में नहीं आता है) is_same_vके संदर्भ में सार्थक नहीं है variant। इसी "लक्षण" है holds_alternative
Pixelchemist

std::variantयहाँ पूरी तरह से अनावश्यक है
tjysdsg

7

आप इस तरह से अपने मापदंडों में पारित किए गए के आधार पर अपने टेम्पलेट्स को विशेषज्ञ कर सकते हैं:

template <> void foo<animal> {

}

ध्यान दें कि यह उस प्रकार के आधार पर एक पूरी तरह से नया फ़ंक्शन बनाता है जो इस प्रकार पारित किया गया है T। यह आमतौर पर बेहतर होता है क्योंकि यह अव्यवस्था को कम करता है और अनिवार्य रूप से कारण है कि हमारे पास पहले स्थान पर टेम्पलेट हैं।


हम्म। क्या यह तरीका वास्तव में खाका तर्क के विशेषज्ञ का एकमात्र पसंदीदा तरीका है? मान लीजिए कि मेरे पास 10 अलग-अलग बाल कक्षाएं हैं जिन्हें मुझे टेम्पलेट फ़ंक्शन के अंदर प्रबंधित करने की आवश्यकता है। क्या मुझे वास्तव में संबंधित वर्ग के लिए 10 अलग-अलग टेम्पलेट फ़ंक्शन लिखने होंगे? मुझे लगता है कि मुझे यहां मूल बिंदु याद आ रहा है।
वोल्कन ग्यूवेन

यह वास्तव में एक अच्छा विचार जैसा लगता है, अगर कोई type_traits का उपयोग नहीं करना चाहता है। जैसे किसी ने उल्लेख किया है कि मुख्य तर्क को एक अलग फ़ंक्शन में किया जा सकता है, जो कि प्रकार को इंगित करने के लिए एक अतिरिक्त ध्वज को स्वीकार करता है, और यह विशेष घोषणा केवल ध्वज को तदनुसार निर्धारित कर सकती है और बिना किसी स्पर्श के सीधे अन्य सभी तर्कों पर पास कर सकती है। तो अगर 10 अलग-अलग वर्गों को संभालने की आवश्यकता है, तो मूल रूप से 10 अलग-अलग फ़ंक्शन परिभाषाओं के लिए 10 लाइनें हैं। लेकिन यह एक बहुत जटिल हो जाएगा अगर 1 से अधिक टेम्पलेट चर हैं।
हरीश गणेशन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.