टेम्पलेट वर्ग के सदस्य समारोह के स्पष्ट विशेषज्ञता


88

मुझे कुछ प्रकार के लिए टेम्प्लेट सदस्य फ़ंक्शन को विशेषज्ञ बनाने की आवश्यकता है (चलो डबल कहते हैं )। यह ठीक काम करता है जबकि क्लास Xखुद एक टेम्प्लेट क्लास नहीं है, लेकिन जब मैं इसे बनाता हूं तो जीसीसी कंपाइल-टाइम एरर देना शुरू कर देता है।

#include <iostream>
#include <cmath>

template <class C> class X
{
public:
   template <class T> void get_as();
};

template <class C>
void X<C>::get_as<double>()
{

}

int main()
{
   X<int> x;
   x.get_as();
}

यहाँ त्रुटि संदेश है

source.cpp:11:27: error: template-id
  'get_as<double>' in declaration of primary template
source.cpp:11:6: error: prototype for
  'void X<C>::get_as()' does not match any in class 'X<C>'
source.cpp:7:35: error: candidate is:
  template<class C> template<class T> void X::get_as()

मैं इसे कैसे ठीक कर सकता हूं और यहां क्या समस्या है?

अग्रिम में धन्यवाद।


2
वर्तमान मानक में यह अवैध है, विशेष करने के लिए, आपको कक्षा को भी विशेषज्ञ बनाना होगा ...
निम

लेकिन यह काम करता है यदि वर्ग टेम्पलेट नहीं है। क्या यह भी अवैध है?
लेडोकॉल

नहींं, यह पूरी तरह से ठीक है, यह केवल क्लास टेम्प्लेट के लिए है जो यह नियम लागू होता है (AFAIK)।
निम

जवाबों:


108

यह उस तरह से काम नहीं करता है। आपको निम्नलिखित कहने की आवश्यकता होगी, लेकिन यह सही नहीं है

template <class C> template<>
void X<C>::get_as<double>()
{

}

स्पष्ट रूप से विशिष्ट सदस्यों को अपने आस-पास के क्लास टेम्प्लेट की आवश्यकता होती है ताकि स्पष्ट रूप से विशेष रूप से अच्छी तरह से विशेष हो। तो आपको निम्नलिखित बातें कहने की जरूरत है, जो केवल सदस्य के लिए विशेषज्ञ होंगे X<int>

template <> template<>
void X<int>::get_as<double>()
{

}

यदि आप आसपास के टेम्पलेट को विशिष्ट रखना चाहते हैं, तो आपके पास कई विकल्प हैं। मुझे ओवरलोड पसंद है

template <class C> class X
{
   template<typename T> struct type { };

public:
   template <class T> void get_as() {
     get_as(type<T>());
   }

private:
   template<typename T> void get_as(type<T>) {

   }

   void get_as(type<double>) {

   }
};

आपको type<>रैपर की आवश्यकता क्यों है ? प्रकार के एक सूचक को 0 का कास्ट नहीं कर सकता Tहै चाल? मुझे लगता है कि यह उतना सुंदर नहीं है ...
निम

ऐसा लगता है कि वास्तव में ऐसा करना संभव नहीं है। धन्यवाद।
ledokol

3
@ ठीक है, मुझे लगता है कि पॉइंटर कास्ट बदसूरत है, और उन प्रकारों के लिए काम नहीं करेगा जिन्हें आप (संदर्भ) इंगित नहीं कर सकते। इसके अलावा, एक फंक्शन पैरामीटर होना एक अरै टाइप प्रकार का पॉइंटर है जो बिना C ++ में अवैध है। एक प्रकार के आवरण में होने से यह सभी प्रकार के काम में आता है।
जोहान्स स्काउब - १२

2
@ जोहान्सचैब-लिटब: ओवरलोड के साथ अन्य विकल्प क्या हैं? उनमें से कुछ दिखा सकते हैं?
जीन-बर्नार्ड जानसेन

2
@ फास्ट-रिफ्लेक्स उनकी टिप्पणी का उपयोग करना template<typename T> void get_as(T*); void get_as(double*);और पास करना था (T*)0
जोहान्स शाउब -

24

यदि कोई इस्तेमाल किया std::enable_ifजा सकता है तो हम SFINAE पर भरोसा कर सकते हैं (प्रतिस्थापन विफलता एक त्रुटि नहीं है)

ऐसा काम करेगा ( LIVE देखें ):

#include <iostream>
#include <type_traits>

template <typename C> class X
{
public:
    template <typename T, 
              std::enable_if_t<!std::is_same_v<double,T>, int> = 0> 
    void get_as() { std::cout << "get as T" << std::endl; }

    template <typename T, 
              std::enable_if_t<std::is_same_v<double,T>, int> = 0> 
    void get_as() { std::cout << "get as double" << std::endl; }
};

int main() {
   X<int> d;
   d.get_as<double>();

   return 0;
}

बदसूरत बात यह है कि, इन सभी के साथ enable_if की केवल एक विशेषज्ञता को संकलक के लिए उपलब्ध होने की आवश्यकता है अन्यथा असंतोष की त्रुटि उत्पन्न होगी। यही कारण है कि डिफ़ॉल्ट व्यवहार "टी के रूप में मिलता है" को भी सक्षम होना चाहिए अगर।


इसे और आधुनिक बनाने के लिए पोस्ट को अपडेट किया।
गेब्रियल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.