2012-06-13 16 views
39

क्या एक के बजाय मूल्यों की एक श्रृंखला के आधार पर टेम्पलेट विशेषज्ञता रखने का कोई तरीका है? मुझे पता है कि निम्न कोड वैध C++ कोड मान्य नहीं है लेकिन यह दिखाता है कि मैं क्या करना चाहता हूं। मैं 8-बिट मशीन के लिए कोड लिख रहा हूं, इसलिए इन्स और वर्णों का उपयोग करने के लिए गति में अंतर है।मैं पूर्णांक मानों की एक श्रृंखला के लिए सी ++ टेम्पलेट का विशेषज्ञ कैसे बना सकता हूं?

template<unsigned SIZE> 
class circular_buffer { 
    unsigned char buffer[SIZE]; 
    unsigned int head; // index 
    unsigned int tail; // index 
}; 

template<unsigned SIZE <= 256> 
class circular_buffer { 
    unsigned char buffer[SIZE]; 
    unsigned char head; // index 
    unsigned char tail; // index 
}; 

उत्तर

45

std::conditional का प्रयास करें:

#include <type_traits> 

template<unsigned SIZE> 
class circular_buffer { 

    typedef typename 
     std::conditional< SIZE < 256, 
          unsigned char, 
          unsigned int 
         >::type 
     index_type; 

    unsigned char buffer[SIZE]; 
    index_type head; 
    index_type tail; 
}; 

अपने संकलक अभी तक सी ++ 11 के इस हिस्से का समर्थन नहीं करता है, वहाँ में बराबर है boost libraries.

फिर फिर, इसे रोल करना आसान है खुद (क्रेडिट KerrekSB को जाता है):

template <bool, typename T, typename F> 
struct conditional { 
    typedef T type; 
}; 

template <typename T, typename F> // partial specialization on first argument 
struct conditional<false, T, F> { 
    typedef F type; 
}; 
+1

मुझे कहना है, यह उपयोगी है। – chris

+6

'std :: conditional' जैसी विशेषता आपके लिखने के लिए तुच्छ है, इसलिए यदि आपके पास यह नहीं है तो आपको वास्तव में किसी भी पुस्तकालय की आवश्यकता नहीं है:' टेम्पलेट <बूल, टाइपनाम टी, टाइपनाम> स्ट्रक्चर सशर्त {typedef टी प्रकार; }; टेम्पलेट <टाइपनाम टी, टाइपनाम यू> स्ट्रक्चर सशर्त {टाइपपीफ यू टाइप; }; ' –

+0

चीयर्स @ केरेक एसबी, मैंने इसे उत्तर में जोड़ा। – jrok

33

उपयोग एक अतिरिक्त bool पैरामीटर चूक:

// primary template handles false 
template<unsigned SIZE, bool IsSmall = SIZE <= 256> 
class circular_buffer { 
    unsigned char buffer[SIZE]; 
    unsigned int head; // index 
    unsigned int tail; // index 
}; 

// specialization for true 
template<unsigned SIZE> 
class circular_buffer<SIZE, true> { 
    unsigned char buffer[SIZE]; 
    unsigned char head; // index 
    unsigned char tail; // index 
}; 
+0

मैं खुश हो जाएगा अगर 'IsSmall = SIZE <= 256' में इसमें माता-पिता थे –

+0

@MooingDuck इस तरह? 'IsSmall = (SIZE <= 256)' –

+3

@MooingDuck की आवश्यकता नहीं है। '<' डिफ़ॉल्ट रूप से कम है। यही कारण है कि 'टेम्पलेट' असंबद्ध है। उलझन में '>' डिफ़ॉल्ट रूप से नज़दीकी टेम्पलेट है और इसके लिए आपको माता-पिता की आवश्यकता है। सी ++ बढ़िया है, है ना? –

7

एक अन्य संभावित विकल्प:

template <unsigned SIZE> 
struct offset_size { 
    typedef typename offset_size<SIZE - 1>::type type; 
}; 

template <> 
struct offset_size<0> { 
    typedef unsigned char type; 
}; 

template <> 
struct offset_size<257> { 
    typedef unsigned int type; 
}; 

template<unsigned SIZE> 
class circular_buffer { 
    unsigned char buffer[SIZE]; 
    typename offset_size<SIZE>::type head; // index 
    typename offset_size<SIZE>::type tail; // index 
}; 

(Ideone example)

+7

आप इतने दुखी हैं, यह बहुत क्रूर w.r.t. है। कंपाइलर 'Offset_size 'संकलित करने का प्रयास करें, कंपाइलर को अरबों टेम्पलेट कक्षाओं को तुरंत चालू करना होगा! – valdo

+0

दरअसल, यदि आप इस तकनीक से सावधान नहीं हैं तो आप 'त्रुटि को ट्रिगर करेंगे: टेम्पलेट तत्काल गहराई अधिकतम ___ '(जीसीसी पर डिफ़ॉल्ट रूप से 500) से अधिक है। – cdhowie

0

मुझे नफरत कैसे गन्दा निपटने प्रकार के साथ हो सकता है इसलिए मैं थोड़ा सरल कुछ प्रस्ताव, लीवरेजिंग constexpr। इस प्रकार व्यवहार भिन्न है जब एक अलग प्रकार की आवश्यकता नहीं है के लिए अनुमति देता है और एक सीमा के भीतर फिट करने के लिए और एक मूल्य के न सिर्फ एक तरफ की जरूरत पते: से प्रेरित होकर

template<bool> struct If; 

constexpr bool InClosedRange(std::size_t Value, std::size_t Lower, std::size_t Upper) 
{ 
    return (Lower <= Value) && (Value <= Upper); 
} 

// Usage: 
template<size_t Width, If<true>> 
class Foo; 

template<size_t Width, If<InClosedRange(Width, 1, 41)>> 
class Foo { /* ... */ }; 

template<size_t Width, If<InClosedRange(Width, 42, 142)>> 
class Foo { /* ... */ }; 

: https://stackoverflow.com/a/9516959/929315

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

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