2011-04-01 14 views
69

की स्पष्ट विशेषज्ञता मुझे किसी प्रकार के लिए टेम्पलेट सदस्य फ़ंक्शन का विशेषज्ञ होना चाहिए (मान लें डबल)। यह ठीक काम करता है जबकि कक्षा 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

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

+0

लेकिन यह काम करता है अगर कक्षा टेम्पलेट नहीं है। क्या यह भी अवैध है? – ledokol

+0

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

उत्तर

85

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

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

} 

स्पष्ट रूप specialized members जरूरत है अपने आसपास के वर्ग टेम्पलेट्स स्पष्ट रूप से और साथ ही विशेष जा रहा है। तो आपको निम्नलिखित कहने की ज़रूरत है, जो केवल 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>) { 

    } 
}; 
+0

आपको 'टाइप <>' रैपर की आवश्यकता क्यों है? 'टी' प्रकार के सूचक के लिए 0 की एक कास्ट नहीं कर सकता है? मुझे लगता है कि यह सुरुचिपूर्ण नहीं है ... – Nim

+0

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

+3

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

13

चाहें, तो एक std::enable_if इस्तेमाल किया हम SFINAE पर भरोसा कर सकता है

कि इतने तरह काम करेंगे (प्रतिस्थापन विफलता कोई त्रुटि नहीं है) में सक्षम है: बदसूरत बात

#include <iostream> 
#include <type_traits> 

template <class C> class X 
{ 
public: 
    template <class T, typename std::enable_if< ! std::is_same<double,T>::value>::type * = nullptr > void get_as(){ 
     std::cout << "get as T" << std::endl; 
    } 


    template <class T, typename std::enable_if< std::is_same<double,T>::value>::type * = nullptr > void get_as(){ 
     std::cout << "get as double" << std::endl; 
    } 
}; 


int main() 
{ 

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

    return 0; 
} 

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