template-klasse nur bestimmte typen erlauben



  • so wie es boost macht 😉 musst halt nach schauen.

    Auf jeden fall müsstest du typetraits implementieren mit denen du die Typen prüfen kannst und dann musst du dir ein Static Assert basteln ( Compile Time Assertion )

    Das schreibe ich dir jetzt nicht als Code denn das ist mir einfach zu viel arbeit.
    Wie gesagt schau dir einfach an wie boost das macht. ( btw, ist boost generell für einige Dinge nützlich deswegen kann eine Installation von boost nicht schaden)

    BR



  • - bitte löschen -



  • Sowas hier sollte gehen:

    template <typename T>
    struct X;
    
    template <>
    struct X<int>
    {
    };
    
    template <>
    struct X<char>
    {
    };
    
    template <typename T>
    struct OnlyIntOrChar : X<T>
    {
    };
    

    Du spezialisiert X nur für int und char z.B.. Wenn jetzt OnlyIntOrChar von X ableiten will, aber T was anderes ist, funktioniert das nicht, weils die Basisklasse nicht gibt. Die Fehlermeldung vom Compiler ist dann zugegebener Maßen nicht sofort einleuchtend, aber es tut das was es soll.

    Mit Typlisten ließe sich das ganze bestimmt noch aufpeppen - allerdings sollte man sich dafür schon mit Template-Metaprogrammierung auskennen. Dazu könnte ich dir das Buch "Modern C++ Design" empfehlen, wenn Du es von Grund auf verstehen willst.



  • Ich hab hier mal eben was zusammen geklaut xD

    //###############################################################################
    struct Empty{};
    template< typename Head  , typename Tail >
       struct TypeList
       {
              typedef Head head;
              typedef Tail tail;              
       };
    
    #define TYPELIST_1( Type1 ) TypeList<Type1,Empty>
    #define TYPELIST_2( Type1 , Type2 ) TypeList<Type1,TYPELIST_1(Type2)>
    #define TYPELIST_3( Type1 , Type2 , Type3 ) TypeList<Type1,TYPELIST_2(Type2,Type3)>
    #define TYPELIST_4( Type1 , Type2 , Type3 , Type4 ) TypeList<Type1,TYPELIST_3(Type2,Type3,Type4)>
    #define TYPELIST_5( Type1 , Type2 , Type3 , Type4 , Type5 ) TypeList<Type1,TYPELIST_4(Type2,Type3,Type4,Type5)>
    
    template < typename TList , typename Type >
      struct IndexOf{};
    
    template < typename Type >
      struct IndexOf< Empty , Type >
      {
         enum { value = -1 };
      };
    
    template < typename T , typename Tail >
      struct IndexOf< TypeList<T , Tail> , T >
      {
         enum { value = 0 };
      };
    
    template < typename Head , typename Tail , typename T >
      struct IndexOf< TypeList<Head,Tail> , T >
      {
        private: 
           enum { temp = IndexOf<Tail,T>::value };
        public:
           enum { value = ( temp == -1 ? -1 : 1 + temp) };
      };
    
    template < class T >
      struct is_integral
      {
         private:
            typedef TYPELIST_4( char , short , int , long ) SignedList;
            typedef TYPELIST_4( unsigned char , unsigned short , unsigned int , unsigned long ) UnsignedList;
            enum { is_signed   = IndexOf<SignedList,T>::value   != -1 };
            enum { is_unsigned = IndexOf<UnsignedList,T>::value != -1 };
         public:
            enum { value =  is_signed || is_unsigned };       
      };
    
    template<bool> struct STATIC_ASSERTION_FAILURE;
    template<>     struct STATIC_ASSERTION_FAILURE<true>{};
    
    #define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
    #define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)
    #define BOOST_DO_JOIN2( X, Y ) X##Y
    
    #define OWN_STATIC_ASSERT(expr ) \
            STATIC_ASSERTION_FAILURE<(expr != 0)> \
                BOOST_JOIN(STATIC_ASSERTION_TEST, __LINE__ )
    //###############################################################################
    
    template < typename IntegralType >
       class MyTemplateClass
       {     
            OWN_STATIC_ASSERT( is_integral<IntegralType>::value );
       };
    
    int main()
    {
    //    MyTemplateClass<double> d; // FEHLER
          MyTemplateClass<int> i; // OK!
    }
    

    Edit: Der teil mit der TypList, IndexOf und is_integral stammt ursprünglich aus Modern C++ Design (bzw der Loki Bibliothek ) http://www.moderncppdesign.com
    Die Static Assert Implementation ist aus Boost http://www.boost.org

    Nur damit das auch gesagt wurde -.-



  • oh, vielen dank, werde mir das mal zu gemüte führen... 🙂



  • mein unterirdisches forschungslabor kamen zu folgendem deutlich eleganteren ergebnis:

    switch(T());//garantiere, daß T integraler typ ist
    

    den code schreibt man in den destruktor der template-klasse.



  • volkardus schrieb:

    mein unterirdisches forschungslabor kamen zu folgendem deutlich eleganteren ergebnis:

    switch(T());//garantiere, daß T integraler typ ist
    

    den code schreibt man in den destruktor der template-klasse.

    😃 👍



  • Walli schrieb:

    volkardus schrieb:

    mein unterirdisches forschungslabor kamen zu folgendem deutlich eleganteren ergebnis:

    switch(T());//garantiere, daß T integraler typ ist
    

    den code schreibt man in den destruktor der template-klasse.

    😃 👍

    Tja Volkard müsste man sein 😎



  • volkardus schrieb:

    mein unterirdisches forschungslabor kamen zu folgendem deutlich eleganteren ergebnis:

    switch(T());//garantiere, daß T integraler typ ist
    

    den code schreibt man in den destruktor der template-klasse.

    struct Klasse
    {
    	operator int(){
    		return 1;
    	}
    };
    
    switch(Klasse()):
    


  • Mit anderen Worten... man nehme ein Stückchen Code, der nur mit den gewünschten Typen funktioniert und verwende diesen im Template...
    *Abrakadabra*
    Schwubs hat man ein typabhängiges Template.



  • otze schrieb:

    volkardus schrieb:

    mein unterirdisches forschungslabor kamen zu folgendem deutlich eleganteren ergebnis:

    switch(T());//garantiere, daß T integraler typ ist
    

    den code schreibt man in den destruktor der template-klasse.

    struct Klasse
    {
    	operator int(){
    		return 1;
    	}
    };
    
    switch(Klasse()):
    

    🕶 Das ist ein fieses Gegenargument

    Aber wahr.


Anmelden zum Antworten