Absolute Typgrößen mit templates



  • Zudem versteh ich nicht ganz, wozu dein SelectIntegerSign::unimportant gut sein soll. Wenn ich das richtig sehe, sind solche Typen doch immer unsigned.

    An sich ja. Die Idee war zu zeigen wie man aus 2 Listen auswählen kann. Der Code ist ja auch so gehalten, dass es leicht ist einen Type zu suchen der andere Bedingungen erfüllt. SelectIntegerSign::unimportant ist also in der Tat überflüssing.



  • hola

    interessante thematik hier. blick zwar noch net so ganz durch, aber sieht interessant aus.
    hab mir nun bissl den kopf zerbrochen wie man ohne dem CHAR_BIT aus der limits.h die bits pro bytes rausbekommen koennte. weiß nur net ob das nun so korrekt is.

    template <unsigned char x, int z = 1>
    class count_bits
    {
       public:
          enum { value = z + count_bits<x >> 1,1>::value };
    };
    
    template <int z>
    class count_bits<0,z>
    {
       public:
          enum { value = 0 };
    };
    
    const unsigned char full_byte = ~0;
    int bits_pro_byte = count_bits<full_byte>::value;
    

    scheinbar funktioniert es auch richtig. aber vielleicht kann man das ja auch noch besser loesen.
    die konstante full_byte hab ich deshalb benuetzt, weil mein BCB meckert wenn ich count_bits direkt ~0 uebergebe.
    Vielleicht kann mir ja jemand sagen, warum das so ist.

    Meep Meep



  • Probiers mit einem Cast, das könnte die Warnung des BCB beseitigen.

    int bits_pro_byte = count_bits<~(unsigned char)(0)>::value;
    

    Allerdings wundert es mich, dass es überhaupt kompiliert. Wahrscheinlich hat da jeder Compiler seine eigene Vorstellung von der Syntax Überprüfung. Mach deshalb noch Klammern in dein Template, dann sollte es überall funktionieren.

    enum { value = z + count_bits<(x >> 1),1>::value };
    

    Und bitte verwende static const, enum ist ein Hack und sollte heute nicht mehr verwendet werden. Wer sich mit Template Metaprogrammierung beschäftigt, für den sind sowieso nur aktuelle Compiler von Interesse und die sollten mittlerweile auch static const für in-class Initialisierung beherrschen.
    Ausserdem kann enum hier Probleme bereiten, zB wenn die interne Darstellung auf einer Plattform genauso gross ist wie ein char.



  • So, ich habe gestern nochmal mit den geposteten Sachen etwas rumgespielt und dies ist nun meine finale Version:

    // wieviel Bit hat ein Byte?
    template <unsigned char Value, size_t N>
    struct compute_bits_per_byte
    {
    	static const size_t result = compute_bits_per_byte<(Value >> 1), N + 1>::result;
    };
    
    template <size_t N>
    struct compute_bits_per_byte<0, N>
    {
    	static const size_t result = N;
    };
    
    // Bit-Version von sizeof
    #define bit_sizeof(x) (sizeof(x) * compute_bits_per_byte<~(unsigned char)(0), 0>::result)
    
    //
    template <class T, class Next>
    struct type_list
    {
    	typedef T type;
    	typedef Next next;
    };
    
    //
    template <bool Condition, class Then, class Else>
    struct if_then_else;
    
    template <class Then, class Else>
    struct if_then_else<false, Then, Else>
    {
    	typedef Else result;
    };
    
    template <class Then, class Else>
    struct if_then_else<true, Then, Else>
    {
    	typedef Then result;
    };
    
    //
    template <size_t Size, class Element>
    struct select_type
    {
    private:
    	typedef typename if_then_else<
    		Size == bit_sizeof(typename Element::type),
    		Element,
    		select_type<Size, typename Element::next>
    		>::result tmp;
    public:
    	typedef typename tmp::type type;
    };
    
    template <size_t Size>
    struct select_type<Size, void>
    {
    // Compilefehler falls kein Typ gefunden
    private:
    	struct type
    	{
    	};
    };
    
    template <bool Signed>
    struct integer_types;
    
    template <>
    struct integer_types<false>
    {
    	typedef
    		type_list<unsigned char,
    		type_list<unsigned short,
    		type_list<unsigned int,
    		type_list<unsigned long,
    		type_list<unsigned long long,
    		void
    		> > > > > content;
    };
    
    template <>
    struct integer_types<true>
    {
    	typedef
    		type_list<signed char,
    		type_list<signed short,
    		type_list<signed int,
    		type_list<signed long,
    		type_list<signed long long,
    		void
    		> > > > > content;
    };
    
    template <size_t Size, bool Signed>
    struct select_integer
    {
    	typedef typename select_type<Size, typename integer_types<Signed>::content>::type result;
    };
    
    typedef
    	type_list<float,
    	type_list<double,
    	type_list<long double,
    	void
    	> > > floating_point_types;
    
    template <size_t Size>
    struct select_floating_point
    {
    	typedef typename select_type<Size, floating_point_types>::type result;
    };
    
    // Bsp
    typedef select_integer<16, false>::result uint16;
    

    Wer Lust hat, kann damit auch Gleitkommatypen definieren. 🙂



  • Ah wie ich sehe sind meine Mitstreiter immer noch fleißig an der Sache dran. Habe selber in letzter Zeit leider keine Zeit mehr gehabt, da die Schule wieder angefangen hat und ich gerade im totalen Prüfungsstress bin, aber diese Woche sind die letzten Klausuren, danach habe ich wieder Zeit und werde mich auch daran setzen.

    Wobei ich, wie früher schon erwähnt, mehr auf die Typliste als auf das ursprüngliche Vorhaben konzentrieren.


Anmelden zum Antworten