2015-08-31 10 views
8

संक्षेप में:टेम्पलेट तर्क के रूप में एक सामान्य enum प्रकार दें

वहाँ एक रास्ता मैं कुछ के साथ एक General टेम्प्लेटेड वर्ग फ़ीड कर सकते हैं कि केवल एक enum प्रकार का प्रतिनिधित्व करते है?/मेरे मामले में काम नहीं करता है

template <typename T> struct General {}; 
struct EnumSpecific : General<any_enum_type> {}; 

<int> बहुत ज्यादा है: की तरह।


मेरे विशिष्ट मामले:

  • एक टेम्प्लेट की Holder वर्ग एक सामान्य तरीके डेटा के किसी भी प्रकार संभालती है।
  • एक सार General कक्षा Holder एस 'व्यवहार पर निर्भर विशिष्ट एल्गोरिदम लागू करती है।
  • General का खाका विनिर्देशों (जैसे IntSpecific, DoubleSpecific, StringSpecific, MoreSophisticatedTypeSpecific ..) कुछ ठोस Holder प्रकार से निपटने के लिए कैसे परिभाषित करते हैं।
  • मैं EnumSpecific विनिर्देश को सही ढंग से कैसे परिभाषित कर सकता हूं?

यहाँ मेरी समस्या बनाने कोड नीचे boilt नहीं की जाती तब:

// A templated value holder: 
template <typename T> 
class Holder { 
public: 
    Holder(T const& t) : _value(t) {}; 
    // generic methods 
    void generics() {}; 
    // methods concerning the value: 
    void set(T const& t /*, setInfo */) { 
     // .. check for an actual change, notify buddies of the change.. 
     _value = t; 
    }; 
    T value(/*readInfo*/) { 
     // .. do stuff depending on how/why the value is read.. 
     return _value; 
    }; 
private: 
    T _value; 
}; 
// (in reality, all `generics` methods come from a parent, untemplated class) 

// A generic process involving such `Holder`s: 
template <typename T> 
class General { 
public: 
    typedef bool /* or anything */ KnownReturnTypes; 
    General(Holder<T>* const a 
      , Holder<T>* const b) 
     : _a(a) 
     , _b(b) 
    {}; 
    void methods() { 
     // Use common behavior of all `Holder`'s 
     _a->generics(); 
     // .. or methods that rely on the actual values: 
     KnownReturnTypes knr(valuedMethods()); 
     if (knr) {} else {} 
     // ... 
    }; 
    // Use polymorphism to adapt to each situation.. 
    virtual KnownReturnTypes valuedMethods() = 0; 
protected: 
    Holder<T>* _a; 
    Holder<T>* _b; 
}; 

// Example of specialization for integral types (there might be others) 
class IntSpecific : General<int> { 
public: 
    IntSpecific(Holder<int>* const a 
       , Holder<int>* const b) 
     : General<int>(a, b) 
    {}; 
    // implement the valuedMethods: 
    virtual KnownReturnTypes valuedMethods() { 
     return _a->value() > _b->value(); // dummy 
    } 
}; 

// Specialization for enum types: 
// * * * class EnumSpecific : General<any_enum_type> { // does not exist * * 
class EnumSpecific : General<int> { 
public: 
    EnumSpecific(Holder<int>* const a 
       , Holder<int>* const b) 
     : General<int>(a, b) 
    {}; 
    // only use properties and methods offered by an enum type: 
    virtual KnownReturnTypes valuedMethods() { 
     return _a->value() == _b->value(); // dummy 
    } 
}; 

// One particular case 
typedef enum {One, Two, Three} Enum; 
typedef Holder<Enum> EnumHolder; 


int main() { 

    // Check that `IntSpecific` works fine. 
    Holder<int>* i(new Holder<int>(3)); 
    Holder<int>* j(new Holder<int>(5)); 
    IntSpecific is(i, j); // ok. 

    // Try the `EnumSpecific` 
    EnumHolder* a(new EnumHolder { One }); 
    EnumHolder* b(new EnumHolder { Two }); 
    EnumSpecific es(static_cast<Holder<int>*>(a) // invalid cast 
        , static_cast<Holder<Enum>*>(b)); // unexpected type 
    // This is because the compiler doesn't know enough about what 
    // EnumSpecific actually *is*. How to tell him more about it? 


    return EXIT_SUCCESS; 
} 

क्या मैं EnumSpecific : General<??> में साथ टेम्पलेट तर्क को खिलाने बातें संकलक के लिए स्पष्ट कर देना चाहिए?

क्या मुझे सामान्य प्रोग्रामिंग से enum_type अवधारणा और अधिक परिष्कृत उपकरण का उपयोग करने की आवश्यकता है?

+3

सी ++ 11 आप 'देता है std :: is_enum': http://en.cppreference.com/w/cpp/types/is_enum –

+0

@AlanStokes कैसे उसे मिठाई! लेकिन यह अपने आप पर एक टेम्पलेट पैरामीटर नहीं खिला सकता है, है ना? यह कलाकारों को कास्ट करने में मेरी मदद कैसे कर सकता है? –

+1

यह लाभदायक रूप से 'enable_if' के साथ उपयोग किया जा सकता है। और 'underlying_type' आपकी कास्ट के साथ मदद कर सकता है, हालांकि मैं कबूल करता हूं कि उस चरण तक आपके कोड में थोड़ा सा खो गया है। –

उत्तर

7

हम इसे std::enable_if और std::is_enum के साथ पूरा कर सकते हैं। एक नमूना के रूप में यह एक वर्ग है जो एक enum प्रकार टेम्पलेट पैरामीटर के रूप में ले जाएगा।

#include <type_traits> 
enum Enum { FOO, BAR}; 

template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr> 
class Test {}; 

int main() 
{ 
    Test<Enum> a; // ok 
    Test<double> b; // error 
} 
+0

आरएफ! मैं यह काम नहीं कर सकता। क्या # कोड शामिल है 'आपके कोड का उपयोग करने के लिए पर्याप्त होना चाहिए? जीसीसी कहते हैं 'त्रुटि:' स्ट्रक्चर std :: enable_if 'में 'टाइप' नाम का कोई प्रकार नहीं। –

+0

वह त्रुटि है जो आपको मिलनी चाहिए। यदि 'enable_if' गलत हो गया है तो' टाइप' टाइपपीफ मौजूद नहीं है और यह एक कंपाइलर त्रुटि बनाता है। त्रुटि के बाद एक नोट होना चाहिए: 'नोट: पूर्व टेम्पलेट तर्कों को गैर-प्रकार के टेम्पलेट पैरामीटर में प्रतिस्थापित करते समय ... – NathanOliver

+0

Wops! बेशक। मैं अभी उलझन में आया क्योंकि 'clang'' टेम्पलेट' लाइन पर त्रुटि स्थित है। यह अभी भी मुझे जादू दिखता है: क्या आप एक अच्छे सी ++ जेनेरिक प्रोग्रामिंग ट्यूटो रोमिंग के बारे में जानते हैं? कुछ 'टेम्पलेट ' से आगे जा रहे हैं और उन नए सी ++ 11 अद्भुत सामान को कवर करते हैं? –

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

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