2013-04-14 6 views
5

मैंने चलती औसत के लिए एक साधारण कक्षा लिखी जिसे एवीआर के साथ उपयोग किया जा सकता है।पूरे वर्ग के शरीर की प्रतिलिपि बनाने और चिपकाने के बिना टेम्पलेट का विशेषज्ञ कैसे करें?

template<typename T, typename Tsum = int32_t> 
class MovingAverage { ... } 

लेकिन अब मैं कॉपी किए बिना ही नाव के लिए इस वर्ग के विशेषज्ञ और पूरी कक्षा शरीर चिपका कर और बदल सभी टी और Tsum फ्लोट करने के लिए और कहा कि मैं दो टेम्पलेट पैरामीटर का उपयोग करने की जरूरत नहीं है चाहता हूँ। Tsum 'sum' चर के लिए प्रकार है जहां टाइप टी के सभी पास किए गए मानों को सारांशित किया गया था। यदि टी 'uint8_t' है, तो योग के लिए 'uint32_t' का उपयोग करना एक अच्छा विचार है, लेकिन फ्लोट या डबल के लिए उच्च परिशुद्धता वाले डेटाटाइप का उपयोग करने की आवश्यकता नहीं है, इसलिए मुझे इस उद्देश्य के लिए केवल एक पैरामीटर चाहिए।

typedef MovingAverage<float, float> MovingAverage<float> 

या इस तरह से:: मैं इसे इस तरह से काम कर सकता था सोचा

template<> 
class MovingAverage<float> : public MovingAverage<float, float> {}; 

लेकिन मैं गलत था और मैं जहां मैं अपने कोड दो बार लिखने के लिए है ही समाधान मिल गया।

क्या कक्षा केवल एक बार लिखने का कोई तरीका है और फिर इसे पसंद करते हैं इस तरह विशेषज्ञ? अग्रिम धन्यवाद!

उत्तर

5

आप एक सरल लक्षण वर्ग

// general version 
template<typename T> 
struct sum_type 
{ 
    typedef int32_t type; 
}; 

// specialized version 
template<> 
struct sum_type<float> 
{ 
    typedef float type; 
}; 

// repeat for double, the solution from @DanielFrey is even more sophisticated 
// as it specializes all floating point types in one sweep. 

लिख सकता है और उसके बाद अपने वर्ग टेम्पलेट में इस प्रकार के निकालने

template<typename T, typename Tsum = typename sum_type<T>::type> 
//         ^^^^^^^^ <-- dependent type disambiguation 
class MovingAverage { ... }; 

ध्यान रखें कि आपके MovingAverage एक नियमित रूप से पैरामिट्रीकृत कार्यान्वयन है यह केवल काम करता है अगर। यदि आप वास्तव में float (उदाहरण के लिए फ्लोटिंग पॉइंट अंकगणित के गैर-सहयोगी चरित्र की देखभाल करने के लिए अभिव्यक्तियों को फिर से लिखना) के लिए कुछ विशेष कर रहे हैं, तो आपको और अधिक काम करने की आवश्यकता है।

यदि आप सी ++ टेम्पलेट्स के साथ काम करने के बारे में गंभीर हैं, तो नजदीक बुकस्टोर तक चलें- C++ Templates: The Complete Guide पुस्तक प्राप्त करें। धारा 15.1 में एक सामान्य संचित वर्ग टेम्पलेट को परिभाषित करने के लिए 15+ पृष्ठ चर्चा है।

+0

पुस्तक के लिए +1, मुझे याद दिलाता है मैं और अधिक पढ़ना चाहिए :) –

+1

@ डैनियलफ्रे पुस्तक अच्छी तरह से पढ़ी गई है, बहुत ही शैक्षिक, सी ++ 11 संस्करण की प्रतीक्षा नहीं कर सकती है। 'Std :: is_floating_point' चाल के लिए – TemplateRex

8

आप Tsum के लिए अलग-अलग डिफ़ॉल्ट प्रकार चाहते हैं, इस उदाहरण के लिए, एक और वर्ग है जो निर्दिष्ट किया जा सकता को आउटसोर्स किया जाना चाहिए:

template< typename, typename = void > 
struct DefaultSum { using type = int32_t; }; 

template< typename T > 
struct DefaultSum< T, typename std::enable_if< 
    std::is_floating_point<T>::value 
>::type > 
{ using type = T; }; 

template<typename T, typename Tsum = typename DefaultSum<T>::type > 
class MovingAverage { ... } 
+0

+1। – TemplateRex

+0

धन्यवाद, @ डैनियल! यह वास्तव में अच्छा है और जीसीसी के साथ पूरी तरह से काम करता है। दुर्भाग्य से मुझे पता चला कि मैंने avr-gcc के लिए बूस्ट टाइप_टिट्स का संस्करण स्थापित नहीं किया है। फिलहाल मैं इसे काम करने के लिए एक स्थापित करने योग्य डेबियन पैकेज के लिए Google खोज रहा हूं। अन्यथा मैं अपने x86_64 स्थापना से आवश्यक भागों को avr-gcc की निर्देशिका में कॉपी करने के लिए कॉपी करता हूं। – user2280245

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

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