Двоичные константы на C++ - и без макросов
От: TepMuHyc  
Дата: 19.03.03 17:05
Оценка: 171 (15)
...Увидел в Q&A статью г-на Шаргина (http://www.rsdn.ru/qna/?Cpp/bin.xml)
про двоичные константы, и пробило меня написать этот в меру бесполезный,
но прикольный опус.

Итак, использование:
  cout <<"0x"<< hex << Ob<10101010>::value << endl;
     //на выходе получаем "0xaa" - вроде бы правильно :-)

  //раскоментарь чтобы увидеть как компилятор ругается на неверные двоичные числа
  //cout <<"0x"<< hex << Ob<1234>::value << endl


И, собственно, сам код:
//генератор ошибок для неверных двоичных чисел
template<int> struct BAD_BINARY_NUMBER;
template<> struct BAD_BINARY_NUMBER<0> {};
template<> struct BAD_BINARY_NUMBER<1> {};

//Собственно, сам двоичный конвертор
template<unsigned V> struct Ob
{
    BAD_BINARY_NUMBER<(V%10)> check;
    enum { value = (V%10) + (Ob<(V/10)>::value << 1) };
};

template<> struct Ob<0>
{
    enum { value = 0 };
};


Проверено и работает на компиляторах:
— Visual C++ 6.0, 7.0, 7.1
— GCC 3.2.2
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re: Версия нумер ДВА
От: TepMuHyc  
Дата: 19.03.03 17:42
Оценка: 37 (3)
...попробовал я свое творение на сжатие и разрыв, и внес следующие дополнения:

— ограничение на длину "двоичного числа" до 8 символов (1 байт) — а то на слишком длинную константу компилеры обижаются
— добавил шаблоны Ob2 (для 2-байтного целого) и Ob4(для 4-байтного)

template<int> struct BAD_BINARY_NUMBER;
template<> struct BAD_BINARY_NUMBER<0> {};
template<> struct BAD_BINARY_NUMBER<1> {};

template<bool> struct BINARY_NUMBER_TOO_LONG;
template<> struct BINARY_NUMBER_TOO_LONG<false> {};

template<unsigned V> struct Ob
{
    BAD_BINARY_NUMBER<(V%10)> digits_check;
    BINARY_NUMBER_TOO_LONG<(V/100000000)> length_check;
    enum { value = (V%10) + (Ob<(V/10)>::value << 1) };
};

template<> struct Ob<0>
{
    enum { value = 0 };
};

template<unsigned V1,unsigned V2> struct Ob2
{
    enum { value = (Ob<V1>::value << 8) + Ob<V2>::value };
};

template<unsigned V1,unsigned V2,unsigned V3,unsigned V4> struct Ob4
{
    enum { value = (Ob2<V1,V2>::value << 16) + Ob2<V3,V4>::value };
};


Использование:
    cout <<"0x"<< hex << Ob<10101010>::value  << endl;
    cout <<"0x"<< hex << Ob2<1010,111>::value << endl;
    cout <<"0x"<< hex << Ob4<11111111,0,1010,111>::value << endl;
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re[2]: Версия нумер ТРИ (багфиксная)
От: TepMuHyc  
Дата: 20.03.03 15:41
Оценка: 48 (4)
Обнаружился весьма серьезный функциональный прогиб связанный с восьмеричной нотацией.
Дело в том что число "10101010" — десятичное, а число начинающееся с нуля "010101010" — уже восьмеричное! Естественно, это обгадило всю малину.

Так что, багфикс.
Все фичи заявленные в предыдущих релизах сохранены.
namespace Ob_impl {
    template<bool> struct BAD_BINARY_NUMBER;
    template<>     struct BAD_BINARY_NUMBER<false> {};
    template<bool> struct BINARY_NUMBER_TOO_LONG;
    template<>     struct BINARY_NUMBER_TOO_LONG<false> {};

    template<unsigned V> struct radix
    {
        enum { isOctal   = ((V % 8)  < 2) && radix<(V/8)>::isOctal }; 
        enum { isDecimal = ((V % 10) < 2) && radix<(V/10)>::isDecimal }; 
        enum { value = isOctal?8:isDecimal?10:0x100    };
    };

    template<> struct radix<0>
    {
        enum { isOctal = true, isDecimal = true, value = 10 };
    };

    template<unsigned V,unsigned R> struct decode 
    {
        enum { value = (V%R) + (decode<(V/R),R>::value * 2) };
    };

    template<> struct decode<0,8>     { enum { value = 0 }; };
    template<> struct decode<0,10>    { enum { value = 0 }; };
    template<> struct decode<0,0x100> { enum { value = 0 }; };
}

template<unsigned V> struct Ob
{
    enum { radix = Ob_impl::radix<V>::value };
    enum { value = Ob_impl::decode<V,radix>::value };
    Ob_impl::BAD_BINARY_NUMBER<radix==0x100> digists_check;
    Ob_impl::BINARY_NUMBER_TOO_LONG<(V/(radix==8?0100000000:100000000))> length_check;
};

template<unsigned V1,unsigned V2> struct Ob2
{
    enum { value = 0x100 * Ob<V1>::value + Ob<V2>::value };
};

template<unsigned V1,unsigned V2,unsigned V3,unsigned V4> struct Ob4
{
    enum { value = 0x10000 * Ob2<V1,V2>::value + Ob2<V3,V4>::value };
};
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re[3]: Версия нумер ЧЕТЫРЕ
От: _nn_ www.nemerleweb.com
Дата: 29.03.03 13:23
Оценка:
Применение union...


union Binary8
{
    struct
    {
        unsigned b0:1;
        unsigned b1:1;
        unsigned b2:1;
        unsigned b3:1;
        unsigned b4:1;
        unsigned b5:1;
        unsigned b6:1;
        unsigned b7:1;
    }bits;
    unsigned char c;
    Binary8(char a) { c=a; }
    Binary8(
        unsigned a0=0,
        unsigned a1=0,
        unsigned a2=0,
        unsigned a3=0,
        unsigned a4=0,
        unsigned a5=0,
        unsigned a6=0,
        unsigned a7=0)
    {
        bits.b0=a0;
        bits.b1=a1;
        bits.b2=a2;
        bits.b3=a3;
        bits.b4=a4;
        bits.b5=a5;
        bits.b6=a6;
        bits.b7=a7;
    }
    Binary8& operator=(const Binary8 &binary)
    {
        c=binary.c;
        return *this;
    }
    bool operator==(const Binary8 &binary) const
    {
        return c==binary.c;
    }
    bool operator!=(const Binary8 &binary) const
    {
        return c!=binary.c;
    }
    bool operator>(const Binary8 &binary) const
    {
        return c>binary.c;
    }
    bool operator<(const Binary8 &binary) const
    {
        return c<binary.c;
    }
    bool operator>=(const Binary8 &binary) const
    {
        return c>=binary.c;
    }
    bool operator<=(const Binary8 &binary) const
    {
        return c<=binary.c;
    }
};


Можно расширить на любое количество бит.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Версия нумер ЧЕТЫРЕ
От: TepMuHyc  
Дата: 31.03.03 11:07
Оценка:
Здравствуйте, _nn_, Вы писали:

N>Применение union...

Ты немного не просек в чем соль...
А соль в том что мое "двоичное" не порождает никакого кода (в отличие от твоего) — все расчеты выполняются на этапе компиляции — в исполнимый код идет только готовое число.
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re[5]: Версия нумер ЧЕТЫРЕ
От: _nn_ www.nemerleweb.com
Дата: 01.04.03 14:00
Оценка:
Здравствуйте, TepMuHyc, Вы писали:

TMH> в исполнимый код идет только готовое число.


Я об этом не подумал.
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.