2015-08-31 14 views
8

:Kısacası

sadece enum tipini temsil Bir konuda bir General şablonu sınıf besleyebilir bir yolu var mı? gibi bir şey:

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

<int> çok fazla/benim durumumda çalışmaz.


Benim spesifik durum:

  • A Holder sınıfı genel bir şekilde her türlü veri işleme şablonlu. Holder s 'davranışına dayanan belirli algoritmaları uygulayan bir General sınıfı, bir soyut . General ait
  • Şablon özellikleri (gibi IntSpecific, DoubleSpecific, StringSpecific, MoreSophisticatedTypeSpecific ..) bazı somut Holder türleri ile nasıl başa tanımlar.
  • EnumSpecific spesifikasyonunu nasıl tanımlayabilirim? İşte

sorunumu yapma kodu aşağı boilt edilir gerçekleşir:

// 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; 
} 
Ben derleyici için net şeyler yapmak için EnumSpecific : General<??> yılında şablon argümanı besleyelim ne

?

Genel programlamadan bir çeşit enum_type kavramı ve daha gelişmiş araçları kullanmam gerekir mi?

+3

C++ 11 'size std :: is_enum' verir: http://en.cppreference.com/w/cpp/types/is_enum –

+0

@AlanStokes nasıl onu tatlı! Ancak bu, bir şablon parametresini kendi başına besleyemez, değil mi? Bu kadroyu gerçekleştirmeme nasıl yardımcı olabilir? –

+1

"enable_if" ile karlı bir şekilde kullanılabilir. Ve 'underlying_type' senin cast ile yardımcı olabilir, itiraf etmeliyim ki bu aşamada kodunda biraz kayıp var. –

cevap

7

Bunu, std::enable_if ve std::is_enum ile yapabiliriz. Örnek olarak bu, bir enum türünü şablon parametresi olarak alacak bir sınıftır.

#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

Arf! Bunu çalışamıyorum. Kodunuzu kullanmak için yeterli olması gereken #include 'mu? gcc, 'error: st struct std :: enable_if ' içinde named type ’olarak adlandırılan hiçbir tip olmadığını söylüyor. –

+0

Bu almanız gereken bir hata. 'enable_if' false iletilirse,' typ' typedef mevcut değildir ve bir derleyici hatası oluşturur. Hatadan sonra bir not olmalıdır: 'not: önceki şablon argümanlarını tip olmayan şablon parametresine değiştirirken ...' – NathanOliver

+0

Wops! Tabii ki. Kafam karıştı çünkü 'clang' hata 'şablon' satırında bulundu. Bu bana hala sihir gösteriyor: İyi bir C++ jenerik programlamanın dolaşımını biliyor musunuz? Şablon 'den daha ileriye gidip yeni C++ 11 şaşırtıcı şeyleri mi kapsıyor? –

İlgili konular