Templates und Typen



  • Hi!

    Kann man bei einer Template-Funktion durch irgendwelche Tricks erkennen, was für Typen übergeben wurden? Also ob POT, Non-POT, Zeiger, oder sonstwas?
    Ich meine sowas schonmal gesehen zu haben, zumindest für (Funktions-?)Zeiger. Ich find im großen weiten Internet aber nichts 😕

    Dankbar für jede Antwort,
    ergebendst,
    Badestrand



  • template<class T>
    struct IsPointer
    {
        enum { result = false };
    };
    
    template<class T>
    struct IsPointer<T*>
    {
        enum { result = true };
    };
    
    template<class T>
    struct IsConst
    {
        enum { result = false };
    };
    
    template<class T>
    struct IsConst<const T>
    {
        enum { result = true };
    }
    
    ...
    

    Für PODs fällt mir nix ein.



  • ui, das ist tricky 🙂 Danke dir!



  • Maybe für POD's das hier:

    template<class T>
    struct IsInt {
    
        enum { result = false };
    };
    
    template<class T>
    struct IsDouble {
    
        enum { result = false };
    };
    
    template<>
    struct IsInt<int> {
    
        enum { result = true };
    };
    
    template<>
    struct IsDouble<double> {
    
        enum { result = true };
    };
    

    Inspiriert von Michael's Code ist mir das eingefallen.



  • hola

    template<class T>
    inline bool is_pointer_type(T value)
    {
       return false;
    }
    
    template<class T>
    inline bool is_pointer_type(T *value)
    {
       return true;
    }
    
    template<class T>
    inline bool IsPod(T&)
    {
       return type_traits<T>::is_pod;
    }
    
    template<class T>
    struct type_traits
    {
       static const bool is_pod     = false;
       static const bool is_integer = false;
       static const bool is_real    = false;
       static const bool is_signed  = false;
    };
    
    template<>
    struct type_traits<char>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = true;
       typedef signed char signed_t;
       typedef unsigned char unsigned_t;
    };
    
    template<>
    struct type_traits<unsigned char>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = false;
       typedef signed char signed_t;
       typedef unsigned char unsigned_t;
    };
    
    template<>
    struct type_traits<short>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = true;
       typedef short signed_t;
       typedef unsigned short unsigned_t;
    };
    
    template<>
    struct type_traits<unsigned short>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = false;
       typedef unsigned short signed_t;
       typedef unsigned short unsigned_t;
    };
    
    template<>
    struct type_traits<int>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = true;
       typedef int signed_t;
       typedef unsigned int unsigned_t;
    };
    
    template<>
    struct type_traits<unsigned int>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = false;
       typedef int signed_t;
       typedef unsigned int unsigned_t;
    };
    
    template<>
    struct type_traits<long long int>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = true;
       typedef long long int signed_t;
       typedef unsigned long long int unsigned_t;
    };
    
    template<>
    struct type_traits<unsigned long long int>
    {
       static const bool is_pod     = true;
       static const bool is_integer = true;
       static const bool is_real    = false;
       static const bool is_signed  = false;
       typedef long long int signed_t;
       typedef unsigned long long int unsigned_t;
    };
    
    template<>
    struct type_traits<float>
    {
       static const bool is_pod = true;
       static const bool is_integer = false;
       static const bool is_real = true;
       static const bool is_signed = true;
    };
    
    template<>
    struct type_traits<double>
    {
       static const bool is_pod = true;
       static const bool is_integer = false;
       static const bool is_real = true;
       static const bool is_signed = true;
    };
    
    template<>
    struct type_traits<bool>
    {
       static const bool is_pod = true;
       static const bool is_integer = true;
       static const bool is_real = false;
       static const bool is_signed = false;
    };
    

    hab ich mir mal zusammengeschrieben, fuer ne BinaryStream klasse.

    Meep Meep



  • Boost.



  • Das sieht gut aus Meep Meep 🙂
    Wollte auch gerade editieren und Trait-Klassen vorschlagen.





  • Mr. N schrieb:

    http://www.boost.org/libs/type_traits/index.html

    Wir bauen uns selber eine Sandburg :p



  • Hallo,
    die Variante mit der expliziten Aufzälung ist für PODs etwas schlecht, da es beliebig viele POD-Typen gibt. Dummerweise lässt sich ein is_pod<T> in Standard-C++ nicht vollständig implementieren. Um wirklich für jedes T definitiv entscheiden zu können, ob es ein POD-Typ ist oder nicht, bedarf es der Mithilfe vom Compiler.

    Eine sehr gut Type-Traits-Library, die alle deine gestellten Fragen beantworten kann, findest du in den boost-Libs (http://www.boost.org/doc/html/boost_typetraits.html).



  • Und was is mit const, volatile und const volatile Zeigern? 🙂

    template< typename T >
    struct is_pointer< T* const >
    {
    	enum { value = true };
    };
    
    template< typename T >
    struct is_pointer< T* volatile >
    {
    	enum { value = true };
    };
    
    template< typename T >
    struct is_pointer< T* const volatile >
    {
    	enum { value = true };
    };
    

    Microsoft bietet übrigens einige Typetrait funktionen an, z.B. __is_pod(): http://msdn2.microsoft.com/en-us/library/ms177194(VS.80).aspx

    Achja, wo wir grad beim sammeln sind! 🙂

    template< typename T1, typename T2 >
    struct is_same
    {
    	enum { value = false };
    };
    
    template< typename T >
    struct is_same< T, T >
    {
    	enum { value = true };
    };
    


  • Gibt es irgendeinen Grund, dass ihr alle noch den 'enum'-Hack verwendet, um den Wert zu definieren? Was spricht bei heutigen Compilern gegen folgenden Code?

    template <typename T>
    struct is_… {
        static bool const value = false;
    };
    


  • Garnichts, aber was spricht gegen den enum-hack? 🙂



  • David_pb schrieb:

    Garnichts, aber was spricht gegen den enum-hack? 🙂

    • Er sieht "hässlich" aus
    • Er versteckt die wahre Semantik des Codes
    • Er verwendet einen falschen Typ (enum/int) statt bool
    • Er braucht zusätzliche geschweifte Klammern, die man auf einer deutschen PC-Tastatur schlecht erreicht (interessiert mich nicht, ich verwende nen Mac)

    Keine schwerwiegenden Gründe (bis auf den zweiten Punkt), aber doch alles in allem Gründe genug für mich.



  • HumeSikkins schrieb:

    Hallo,
    die Variante mit der expliziten Aufzälung ist für PODs etwas schlecht, da es beliebig viele POD-Typen gibt. Dummerweise lässt sich ein is_pod<T> in Standard-C++ nicht vollständig implementieren.

    werden dann klassen und strukturen die aus reinen pods bestehen auch als pod gewerted ? oder wie ist das zu verstehen ?

    Meep Meep



  • Naja, die Punkte 1 und 4 find ich nich soo überzeugend, aber 2 und 3 haben was! 🙂

    Meep Meep schrieb:

    HumeSikkins schrieb:

    Hallo,
    die Variante mit der expliziten Aufzälung ist für PODs etwas schlecht, da es beliebig viele POD-Typen gibt. Dummerweise lässt sich ein is_pod<T> in Standard-C++ nicht vollständig implementieren.

    werden dann klassen und strukturen die aus reinen pods bestehen auch als pod gewerted ? oder wie ist das zu verstehen ?

    Meep Meep

    Ja. Siehe: http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7


Anmelden zum Antworten