2013-02-22 25 views
5

मान लीजिए मैं निम्नलिखित वर्ग है:सी ++ अनुमान टेम्पलेट अन्य टेम्पलेट तर्क के आधार पर तर्क

template <class T, class U, class V> Foo 
{ 
    ... 
}; 

टेम्प्लेट पैरामीटर एक अलग मानचित्रण है, इसलिए मैं अन्य टेम्पलेट तर्क यू और वी क्या टी है के आधार पर यह मान सकते हैं । उदाहरण के लिए, यदि टी डबल है, तो यू और वी हमेशा कुछ कक्षाएं डी 1 और डी 2 होंगी, और यदि टी फ्लोट हो, तो यू और वी हमेशा कुछ अन्य वर्ग एफ 1 और एफ 2 होंगे।

इस बात को ध्यान में रखते हुए, क्या मैं एकमात्र टेम्पलेट तर्क में पास कर सकता हूं, और संकलक अन्य दो पैरामीटर को कम कर सकता है?

मुझे पता है कि सरल उत्तर यह होगा कि इन अन्य वर्गों को भी टेम्पलेट किया जाए और टेम्पलेट तर्क टी को पास कर दें, लेकिन मैं इन कक्षाओं को टेम्पलेट (वे एक उपकरण द्वारा स्वत: जेनरेट नहीं कर सकते हैं) बनाने में सक्षम नहीं हैं।

आदर्श रूप में मैं बहुत की तरह typedef या #define का उपयोग करने में सक्षम होगा:

typedef Foo<double> Foo<double, D1, D2> 
typedef Foo<float> Foo<float, F1, F2> 

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

उत्तर

5

जवाब Angew द्वारा दिए गए आप सही दृष्टिकोण से पता चलता है, लेकिन आप नहीं दिखा कैसे स्थितियों से निपटने के लिए जहां U और V निष्कर्ष निकाला नहीं जा सकता है और instantiating ग्राहक द्वारा प्रदान किया जाना चाहिए है।

struct D1 { }; struct D2 { }; 
struct F1 { }; struct F2 { }; 

// Primary template 
template<typename T> 
struct deduce_from 
{ 
}; 

// Specialization for double: U -> D1, V -> D2 
template<> 
struct deduce_from<double> 
{ 
    typedef D1 U; 
    typedef D2 V; 
}; 

// Specialization for float: U -> F1, V -> F2 
template<> 
struct deduce_from<float> 
{ 
    typedef F1 U; 
    typedef F2 V; 
}; 

// Give defaults to U and V: if deduce_from is not specialized for 
// the supplied T, and U or V are not explicitly provided, a compilation 
// error will occur 
template< 
    typename T, 
    typename U = typename deduce_from<T>::U, 
    typename V = typename deduce_from<T>::V 
    > 
struct Foo 
{ 
    typedef U typeU; 
    typedef V typeV; 
}; 

और यहाँ है इसके बाद के संस्करण समाधान की शुद्धता का परीक्षण करने के लिए एक सरल कार्यक्रम:

#include <type_traits> 

int main() 
{ 
    static_assert(std::is_same<Foo<double>::typeU, D1>::value, "Error!"); 
    static_assert(std::is_same<Foo<double>::typeV, D2>::value, "Error!"); 
    static_assert(std::is_same<Foo<float>::typeU, F1>::value, "Error!"); 
    static_assert(std::is_same<Foo<float>::typeV, F2>::value, "Error!"); 

    // Uncommenting this will give you an ERROR! 
    // No deduced types for U and V when T is int 
    /* static_assert(
     std::is_same<Foo<int>::typeU, void>::value, "Error!" 
     ); */ 
    static_assert(
     std::is_same<Foo<int, bool, char>::typeU, bool>::value, "Error!" 
     ); // OK 
    static_assert(
     std::is_same<Foo<int, bool, char>::typeV, char>::value, "Error!" 
     ); // OK 
} 
+0

धन्यवाद! यह पूरी तरह से काम करता है। – thompsonja

+0

@ थॉम्पसोनजा: खुशी हुई इससे मदद मिली :-) –

6

आप U और V से छुटकारा पाने सकता है इस तरह:

template <typename T> 
struct Foo 
{ 
    typedef typename deduce_from<T>::U U; 
    typedef typename deduce_from<T>::V V; 
}; 

जहां deduce_from कटौती प्रक्रिया समाहित।

+0

इस मामले को संभालने के लिए, आपको डिफ़ॉल्ट तर्क टेम्पलेट के लिए U और V मानकों आवंटित कर सकते हैं 'Deduce_from' जैसी कक्षा को अक्सर" लक्षण वर्ग "के रूप में जाना जाता है। –

+0

धन्यवाद! एंडी के साथ संयुक्त आपके उत्तर ने मुझे समस्या हल करने में मदद की। – thompsonja

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