2012-04-17 9 views
5

मैं उन्हें कई बार लिखने से बचने के लिए एक साथ विशेषज्ञता समूह बनाने की कोशिश कर रहा हूं। उदाहरण के लिए, नीचे दिए गए कोड में, मैं foo :: func() के कार्यान्वयन के एक मामले के रूप में "फ्लोट" और "डबल" विशेषज्ञ का प्रयास करने की कोशिश करता हूं; मैं फिर "बूल" के लिए एक और कार्यान्वयन का उपयोग करता हूं।इस आश्रित प्रकार को टेम्पलेट तर्क का उपयोग करके विशेषज्ञता के रूप में क्यों नहीं माना जाता है?

template<typename T> struct foo; 

template<typename T> struct bar; 
template<> struct bar<float> { typedef float Type; }; 
template<> struct bar<double> { typedef double Type; }; 

/* specialize for float and double here */ 
template<typename T> struct foo<typename bar<T>::Type> { 
    static void func() { ... } 
}; 

template<> struct foo<bool> { 
    static void func() { ... } 
}; 

यह त्रुटियां जीसीसी 4.4.3 में बाहर हैं। (यह एक लक्ष्य संकलक है, क्योंकि यह Ubuntu सर्वर 10.04 LTS है, जो कथित तौर पर तीन साल रहना पड़ता है के लिए शेयर है।) त्रुटि है:

foo.cpp:8: error: template parameters not used in partial specialization: 
foo.cpp:8: error:   ‘T’ 

त्रुटि ("के लिए foo की पहली विशेषज्ञता को दर्शाता है फ्लोट "और" डबल। ")

मुझे नहीं लगता कि सी ++ का मैं कौन सा हिस्सा यहां उल्लंघन कर रहा हूं - अगर कोई अध्याय और कविता जानता है, तो मैं इसकी सराहना करता हूं। इसके अलावा, अगर कोई एक ही लक्ष्य को पूरा करने का एक और तरीका जानता है (अनावश्यक रूप से वर्बोज़ कोड के बिना, प्रकार के कुछ समूहों के लिए विशेषज्ञता का पुन: उपयोग करना), तो मैं किसी भी सुझाव की भी सराहना करता हूं!

उत्तर

6
template<typename T> struct foo<typename bar<T>::Type> { 
    static void func() { ... } 
}; 

आप गैर-deducible संदर्भ में T का उपयोग कर रहे हैं, इसलिए संकलक T को घटा नहीं सकता है भले ही यह bar<T>::Type के मान को जानता हो।

मान लीजिए आप लिखते हैं,

foo<double> foodouble; 

तो आप शायद लगता है, bar जो double साथ विशेष है का चयन किया जाएगा जब foo instantiating?

template<> struct bar<int> { typedef double Type; }; 

अब bar<double>::Type और bar<int>::Type दोनों double दे: केवल तभी संकलक लगता है कि वहाँ bar का एक और विशेषज्ञता है जो इस तरह नेस्टेड प्रकार, कुछ के रूप में परिभाषित करता है double मौजूद नहीं है कर सकते हैं कि उचित लगता है। तो नीचे की रेखा है: bar की विशेषज्ञता की असीमित संख्या मौजूद हो सकती है, जिनमें से सभी double को नेस्टेड प्रकार के रूप में प्रदान कर सकते हैं, जिससे विशिष्ट रूप सेbar कक्षा टेम्पलेट के लिए टेम्पलेट तर्क को कम कर देता है।

#include <iostream> 

template<typename T> struct bar { typedef void type; }; 
template<> struct bar<float> { typedef bar<float> type; }; 
template<> struct bar<double> { typedef bar<double> type; }; 

template<typename T> 
struct foo : bar<T>::type 
{ 
    static void func() 
    { 
     std::cout << "primary template for float and double" << std::endl; 
    } 
}; 

template<> 
struct foo<bool> 
{ 
    static void func() 
    { 
     std::cout << "specialization for for bool" << std::endl; 
    } 
}; 

int main() 
{ 
    foo<float>::func(); 
    foo<double>::func(); 
    foo<bool>::func(); 
} 

आउटपुट (online demo):

primary template for float and double 
primary template for float and double 
specialization for for bool 

ध्यान दें कि struct foo : bar<T>::type एक विशेषज्ञता अब और नहीं है


आप SFINAE के रूप में उपयोग कर सकते हैं। यह एक प्राथमिक टेम्पलेट है। यह भी ध्यान रखें कि यह वही नहीं हो सकता है जो आप चाहते हैं, क्योंकि यह float, double और bool के अलावा अन्य तर्क के साथ वर्ग टेम्पलेट के सभी तत्कालताओं को अक्षम करता है; उदाहरण के लिए, आप foo<int> का उपयोग नहीं कर सकते हैं। लेकिन फिर मैं यह भी ध्यान देता हूं कि आपने प्राथमिक टेम्पलेट को अनिर्धारित छोड़ दिया है, इसलिए मुझे आशा है कि यह समाधान आपकी आवश्यकता के साथ फिट बैठेगा।

+0

यदि एक ही प्रकार की घोषणा के साथ मल्टीपल बार हैं तो मुझे "संदिग्ध टेम्पलेट विनिर्देश" त्रुटि प्राप्त करने में पूरी तरह से खुशी होगी। कंपाइलर में वास्तव में इसकी सारी जानकारी होती है। उत्सुकता से, एक दोस्त रिपोर्ट करता है कि यह घोषणा मैकोज़ एक्स पर जीसीसी 4.1 पर काम करती है। वैसे भी - उत्तर के लिए धन्यवाद, और सुझाए गए कार्य-आसपास। ऐसा लगता है कि मेरे लिए काम कर सकता है! –

2

मुझे नहीं लगता कि आप जो प्रयास कर रहे हैं वह संभव है। मुझे एक समान प्रश्न here मिला। मेरे पास कोई लिंक नहीं है, लेकिन सी ++ मानक का प्रासंगिक खंड 14.8.2.5 है। इसलिए तर्क निष्कर्ष निकाला जा सकता है,

The non-deduced contexts are: 
— The nested-name-specifier of a type that was specified using a qualified-id. 
— A non-type template argument or an array bound in which a subexpression references a template 
parameter. 
— A template parameter used in the parameter type of a function parameter that has a default argument 
that is being used in the call for which argument deduction is being done. 
— A function parameter for which argument deduction cannot be done because the associated function 
argument is a function, or a set of overloaded functions (13.4), and one or more of the following apply: 
— more than one function matches the function parameter type (resulting in an ambiguous deduc- 
tion), or 
— no function matches the function parameter type, or 
— the set of functions supplied as an argument contains one or more function templates. 
— A function parameter for which the associated argument is an initializer list (8.5.4) but the parameter 
does not have std::initializer_list or reference to possibly cv-qualified std::initializer_list 
type. [ Example: 
template<class T> void g(T); 
g({1,2,3}); 
// error: no argument deduced for T 
— end example ] 
— A function parameter pack that does not occur at the end of the parameter-declaration-clause. 

अपने मामले में आप प्रकार एक योग्य आईडी का उपयोग कर निर्दिष्ट करते हैं: यहाँ टेम्पलेट तर्क की कटौती पर अनुभाग से एक उद्धरण है।

यह एक त्वरित समाधान का आप कम महत्वपूर्ण चीज़ों के लिए एक दूसरी गैर प्रकार bool पैरामीटर जोड़ सकता है के रूप में, बहुत ज्यादा सोचा दे बिना

- तरह कुछ:

भाग्य का
template<typename T, bool is_decimal = false> 
struct foo {...}; // general case 

template<typename T> 
struct foo<T, true> { ... }; // case where T is float or double 

बेस्ट ...

+0

संदर्भ के लिए अंक! दुख की बात है कि टी स्पष्ट रूप से अप्रसन्न है, भले ही (इस मामले में) इसे घटाया जा सके, और अस्पष्टता या उचित तरीके से पता नहीं लगाया जा सके। –

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