Boost logo

Boost :

Subject: [boost] Library proposal: binconst, constant of the binary form.
From: TaeKyeong Wang (bugiii_at_[hidden])
Date: 2009-01-14 22:14:36


C++ programmers want to input a constant of the binary form, like
following. But, this is illegal in C++ world.

    unsigned char value = 0b10001010;

There are some solutions of this lack. But, I can't find the gratifying answer.

This proposal has following features.

    - whether digits is binary form
    - whether digits is octal or decimal of binary form
    - range of input octal or decimal number detection
    - output value is absolutely constant, no charge of resource
(code, memory) at a run-time

Usage:

    unsigned int td = BD_( 10101010, 00101100, 11110000, 00001111 ); // OK
    unsigned short tw = BW_( 00011000, 12345678 ); // Compile Error -
invalid binary digit
    unsigned char tb1 = BB_( 0101 ); // OK. from octal
    unsigned char tb2 = BB_( 1010 ); // OK. from decimal
    unsigned char tb3 = BB_( 0111100001 ); // Compile Error - out of octal range
    unsigned char tb4 = BB_( 111100001 ); // Compile Error - out of
decimal range

Thanks.

---------- binconst.h
template<int>
struct CompileTimeCheck;

template<>
struct CompileTimeCheck<true>
{
};

/**
        Determines whether N is octal digits of the binary form.

        ex 1)
                octal_test< 0101 > == octal_test< 65 >, 65 % 8 == 1
                octal_test< 0010 > == octal_test< 8 >, 8 % 8 == 1
                octal_test< 0001 > == octal_test< 1 >, 1 % 8 == 1
                octal_test< 0000 > == octal_test< 0 >, 0 % 8 == 0
        ex 2)
                octal_test< 0120 > == octal_test< 80 >, 80 % 8 == 0
                octal_test< 0012 > == octal_test< 10 >, 10 % 8 == 2 <--- invalid
digit detected!!!
                octal_test< 0001 > == octal_test< 1 >, 1 % 8 == 1
                octal_test< 0000 > == octal_test< 0 >, 0 % 8 == 0
*/
template< unsigned int N >
struct octal_test
{
        enum {
                is_octal = (N % 8 <= 1) & octal_test< N / 8 >::is_octal
        };

};

/**
        end recursive
*/
template<>
struct octal_test< 0 >
{
        enum { is_octal = 1 };
};

/**
        Determines whether N is decimal digits of the binary form.
*/
template< unsigned int N >
struct decimal_test
{
        enum {
                is_decimal = (N % 10 <= 1) & decimal_test< N / 10 >::is_decimal,
        };
};

/**
        end recursive
*/
template<>
struct decimal_test< 0 >
{
        enum { is_decimal = 1 };
};

/**
        Convert octal digits of the binary form to a binary number.
*/
template< unsigned int N >
struct binary_octal
{
        enum {
                value = N % 8 + 2 * binary_octal< N / 8 >::value
        };
};

/**
        end recursive
*/
template<>
struct binary_octal< 0 >
{
        enum { value = 0 };
};

/**
        Convert decimal digits of the binary form to a binary number.
*/
template< unsigned int N >
struct binary_decimal
{
        enum {
                value = N % 10 + 2 * binary_decimal< N / 10 >::value
        };
};

/**
        end recursive
*/
template<>
struct binary_decimal< 0 >
{
        enum { value = 0 };
};

/**
        one byte
*/
template< unsigned int B0 >
struct binary_byte
{
        enum {
                is_octal = octal_test< B0 >::is_octal,
                is_decimal = decimal_test< B0 >::is_decimal
        };

        static const unsigned int value =
                is_decimal ?
                binary_decimal< B0 >::value :
                binary_octal< B0 >::value;

        CompileTimeCheck< is_octal * B0 <= 011111111 > Out_Of_Range_Octal;
        CompileTimeCheck< is_decimal * B0 <= 11111111 > Out_Of_Range_Decimal;
        CompileTimeCheck< is_octal | is_decimal > Invalid_Binary_Digit;
};

/**
        two bytes
*/
template< unsigned int B1, unsigned int B0 >
struct binary_word
{
        static const unsigned int value =
                (binary_byte< B1 >::value << 8) +
                (binary_byte< B0 >::value);
};

/**
        four bytes
*/
template< unsigned int B3, unsigned int B2, unsigned int B1, unsigned int B0 >
struct binary_dword
{
        static const unsigned int value =
                (binary_word< B3, B2>::value << 16) +
                binary_word< B1, B0 >::value;
};

#define BB_( b0 ) \
        binary_byte< b0 >::value

#define BW_( b1, b0 ) \
        binary_word< b1, b0 >::value

#define BD_( b3, b2, b1, b0 ) \
        binary_dword< b3, b2, b1, b0 >::value

---------- binconst_test.cpp
#include "binconst.h"

const unsigned int testd = BD_( 11111111, 00000000, 00000000, 00000101 );

#define CHECK( c ) \
{ \
        CompileTimeCheck< (c) > error; \
        (void)error; \
}

int main()
{
        /*
                Generated assembly code
                
                Visual C++ 2008 Express Edition
                mov DWORD PTR _bd$[ebp], -16777211 ; ff000005H

                g++ (GCC) 4.2.1 20070719 [FreeBSD]
                movl $-16777211, -4(%ebp)
        */
        dword bd = BD_( 11111111, 00000000, 00000000, 00000101 );

        CHECK( BD_( 11111111, 00000000, 00000000, 00000101 ) == 0XFF000005 );

        CHECK( BB_( 0 ) == 0x0 );
        CHECK( BB_( 1 ) == 0x1 );

        CHECK( BB_( 00 ) == 0x0 );
        CHECK( BB_( 01 ) == 0x1 );
        CHECK( BB_( 10 ) == 0x2 );
        CHECK( BB_( 11 ) == 0x3 );

        CHECK( BB_( 000 ) == 0x0 );
        CHECK( BB_( 001 ) == 0x1 );
        CHECK( BB_( 010 ) == 0x2 );
        CHECK( BB_( 011 ) == 0x3 );
        CHECK( BB_( 100 ) == 0x4 );
        CHECK( BB_( 101 ) == 0x5 );
        CHECK( BB_( 110 ) == 0x6 );
        CHECK( BB_( 111 ) == 0x7 );

        CHECK( BB_( 0000 ) == 0x0 );
        CHECK( BB_( 0001 ) == 0x1 );
        CHECK( BB_( 0010 ) == 0x2 );
        CHECK( BB_( 0011 ) == 0x3 );
        CHECK( BB_( 0100 ) == 0x4 );
        CHECK( BB_( 0101 ) == 0x5 );
        CHECK( BB_( 0110 ) == 0x6 );
        CHECK( BB_( 0111 ) == 0x7 );
        CHECK( BB_( 1000 ) == 0x8 );
        CHECK( BB_( 1001 ) == 0x9 );
        CHECK( BB_( 1010 ) == 0xA );
        CHECK( BB_( 1011 ) == 0xB );
        CHECK( BB_( 1100 ) == 0xC );
        CHECK( BB_( 1101 ) == 0xD );
        CHECK( BB_( 1110 ) == 0xE );
        CHECK( BB_( 1111 ) == 0xF );

        CHECK( BB_( 00000000 ) == 0x00 );
        CHECK( BB_( 00000001 ) == 0x01 );
        CHECK( BB_( 00000010 ) == 0x02 );
        CHECK( BB_( 00000011 ) == 0x03 );
        CHECK( BB_( 00000100 ) == 0x04 );
        CHECK( BB_( 00000101 ) == 0x05 );
        CHECK( BB_( 00000110 ) == 0x06 );
        CHECK( BB_( 00000111 ) == 0x07 );
        CHECK( BB_( 00001000 ) == 0x08 );
        CHECK( BB_( 00001001 ) == 0x09 );
        CHECK( BB_( 00001010 ) == 0x0A );
        CHECK( BB_( 00001011 ) == 0x0B );
        CHECK( BB_( 00001100 ) == 0x0C );
        CHECK( BB_( 00001101 ) == 0x0D );
        CHECK( BB_( 00001110 ) == 0x0E );
        CHECK( BB_( 00001111 ) == 0x0F );

        CHECK( BB_( 00010000 ) == 0x10 );
        CHECK( BB_( 00010001 ) == 0x11 );
        CHECK( BB_( 00010010 ) == 0x12 );
        CHECK( BB_( 00010011 ) == 0x13 );
        CHECK( BB_( 00010100 ) == 0x14 );
        CHECK( BB_( 00010101 ) == 0x15 );
        CHECK( BB_( 00010110 ) == 0x16 );
        CHECK( BB_( 00010111 ) == 0x17 );
        CHECK( BB_( 00011000 ) == 0x18 );
        CHECK( BB_( 00011001 ) == 0x19 );
        CHECK( BB_( 00011010 ) == 0x1A );
        CHECK( BB_( 00011011 ) == 0x1B );
        CHECK( BB_( 00011100 ) == 0x1C );
        CHECK( BB_( 00011101 ) == 0x1D );
        CHECK( BB_( 00011110 ) == 0x1E );
        CHECK( BB_( 00011111 ) == 0x1F );

        CHECK( BB_( 00100000 ) == 0x20 );
        CHECK( BB_( 00100001 ) == 0x21 );
        CHECK( BB_( 00100010 ) == 0x22 );
        CHECK( BB_( 00100011 ) == 0x23 );
        CHECK( BB_( 00100100 ) == 0x24 );
        CHECK( BB_( 00100101 ) == 0x25 );
        CHECK( BB_( 00100110 ) == 0x26 );
        CHECK( BB_( 00100111 ) == 0x27 );
        CHECK( BB_( 00101000 ) == 0x28 );
        CHECK( BB_( 00101001 ) == 0x29 );
        CHECK( BB_( 00101010 ) == 0x2A );
        CHECK( BB_( 00101011 ) == 0x2B );
        CHECK( BB_( 00101100 ) == 0x2C );
        CHECK( BB_( 00101101 ) == 0x2D );
        CHECK( BB_( 00101110 ) == 0x2E );
        CHECK( BB_( 00101111 ) == 0x2F );

        CHECK( BB_( 00110000 ) == 0x30 );
        CHECK( BB_( 00110001 ) == 0x31 );
        CHECK( BB_( 00110010 ) == 0x32 );
        CHECK( BB_( 00110011 ) == 0x33 );
        CHECK( BB_( 00110100 ) == 0x34 );
        CHECK( BB_( 00110101 ) == 0x35 );
        CHECK( BB_( 00110110 ) == 0x36 );
        CHECK( BB_( 00110111 ) == 0x37 );
        CHECK( BB_( 00111000 ) == 0x38 );
        CHECK( BB_( 00111001 ) == 0x39 );
        CHECK( BB_( 00111010 ) == 0x3A );
        CHECK( BB_( 00111011 ) == 0x3B );
        CHECK( BB_( 00111100 ) == 0x3C );
        CHECK( BB_( 00111101 ) == 0x3D );
        CHECK( BB_( 00111110 ) == 0x3E );
        CHECK( BB_( 00111111 ) == 0x3F );

        CHECK( BB_( 01000000 ) == 0x40 );
        CHECK( BB_( 01000001 ) == 0x41 );
        CHECK( BB_( 01000010 ) == 0x42 );
        CHECK( BB_( 01000011 ) == 0x43 );
        CHECK( BB_( 01000100 ) == 0x44 );
        CHECK( BB_( 01000101 ) == 0x45 );
        CHECK( BB_( 01000110 ) == 0x46 );
        CHECK( BB_( 01000111 ) == 0x47 );
        CHECK( BB_( 01001000 ) == 0x48 );
        CHECK( BB_( 01001001 ) == 0x49 );
        CHECK( BB_( 01001010 ) == 0x4A );
        CHECK( BB_( 01001011 ) == 0x4B );
        CHECK( BB_( 01001100 ) == 0x4C );
        CHECK( BB_( 01001101 ) == 0x4D );
        CHECK( BB_( 01001110 ) == 0x4E );
        CHECK( BB_( 01001111 ) == 0x4F );

        CHECK( BB_( 01010000 ) == 0x50 );
        CHECK( BB_( 01010001 ) == 0x51 );
        CHECK( BB_( 01010010 ) == 0x52 );
        CHECK( BB_( 01010011 ) == 0x53 );
        CHECK( BB_( 01010100 ) == 0x54 );
        CHECK( BB_( 01010101 ) == 0x55 );
        CHECK( BB_( 01010110 ) == 0x56 );
        CHECK( BB_( 01010111 ) == 0x57 );
        CHECK( BB_( 01011000 ) == 0x58 );
        CHECK( BB_( 01011001 ) == 0x59 );
        CHECK( BB_( 01011010 ) == 0x5A );
        CHECK( BB_( 01011011 ) == 0x5B );
        CHECK( BB_( 01011100 ) == 0x5C );
        CHECK( BB_( 01011101 ) == 0x5D );
        CHECK( BB_( 01011110 ) == 0x5E );
        CHECK( BB_( 01011111 ) == 0x5F );

        CHECK( BB_( 01100000 ) == 0x60 );
        CHECK( BB_( 01100001 ) == 0x61 );
        CHECK( BB_( 01100010 ) == 0x62 );
        CHECK( BB_( 01100011 ) == 0x63 );
        CHECK( BB_( 01100100 ) == 0x64 );
        CHECK( BB_( 01100101 ) == 0x65 );
        CHECK( BB_( 01100110 ) == 0x66 );
        CHECK( BB_( 01100111 ) == 0x67 );
        CHECK( BB_( 01101000 ) == 0x68 );
        CHECK( BB_( 01101001 ) == 0x69 );
        CHECK( BB_( 01101010 ) == 0x6A );
        CHECK( BB_( 01101011 ) == 0x6B );
        CHECK( BB_( 01101100 ) == 0x6C );
        CHECK( BB_( 01101101 ) == 0x6D );
        CHECK( BB_( 01101110 ) == 0x6E );
        CHECK( BB_( 01101111 ) == 0x6F );

        CHECK( BB_( 01110000 ) == 0x70 );
        CHECK( BB_( 01110001 ) == 0x71 );
        CHECK( BB_( 01110010 ) == 0x72 );
        CHECK( BB_( 01110011 ) == 0x73 );
        CHECK( BB_( 01110100 ) == 0x74 );
        CHECK( BB_( 01110101 ) == 0x75 );
        CHECK( BB_( 01110110 ) == 0x76 );
        CHECK( BB_( 01110111 ) == 0x77 );
        CHECK( BB_( 01111000 ) == 0x78 );
        CHECK( BB_( 01111001 ) == 0x79 );
        CHECK( BB_( 01111010 ) == 0x7A );
        CHECK( BB_( 01111011 ) == 0x7B );
        CHECK( BB_( 01111100 ) == 0x7C );
        CHECK( BB_( 01111101 ) == 0x7D );
        CHECK( BB_( 01111110 ) == 0x7E );
        CHECK( BB_( 01111111 ) == 0x7F );

        CHECK( BB_( 10000000 ) == 0x80 );
        CHECK( BB_( 10000001 ) == 0x81 );
        CHECK( BB_( 10000010 ) == 0x82 );
        CHECK( BB_( 10000011 ) == 0x83 );
        CHECK( BB_( 10000100 ) == 0x84 );
        CHECK( BB_( 10000101 ) == 0x85 );
        CHECK( BB_( 10000110 ) == 0x86 );
        CHECK( BB_( 10000111 ) == 0x87 );
        CHECK( BB_( 10001000 ) == 0x88 );
        CHECK( BB_( 10001001 ) == 0x89 );
        CHECK( BB_( 10001010 ) == 0x8A );
        CHECK( BB_( 10001011 ) == 0x8B );
        CHECK( BB_( 10001100 ) == 0x8C );
        CHECK( BB_( 10001101 ) == 0x8D );
        CHECK( BB_( 10001110 ) == 0x8E );
        CHECK( BB_( 10001111 ) == 0x8F );

        CHECK( BB_( 10010000 ) == 0x90 );
        CHECK( BB_( 10010001 ) == 0x91 );
        CHECK( BB_( 10010010 ) == 0x92 );
        CHECK( BB_( 10010011 ) == 0x93 );
        CHECK( BB_( 10010100 ) == 0x94 );
        CHECK( BB_( 10010101 ) == 0x95 );
        CHECK( BB_( 10010110 ) == 0x96 );
        CHECK( BB_( 10010111 ) == 0x97 );
        CHECK( BB_( 10011000 ) == 0x98 );
        CHECK( BB_( 10011001 ) == 0x99 );
        CHECK( BB_( 10011010 ) == 0x9A );
        CHECK( BB_( 10011011 ) == 0x9B );
        CHECK( BB_( 10011100 ) == 0x9C );
        CHECK( BB_( 10011101 ) == 0x9D );
        CHECK( BB_( 10011110 ) == 0x9E );
        CHECK( BB_( 10011111 ) == 0x9F );

        CHECK( BB_( 10100000 ) == 0xA0 );
        CHECK( BB_( 10100001 ) == 0xA1 );
        CHECK( BB_( 10100010 ) == 0xA2 );
        CHECK( BB_( 10100011 ) == 0xA3 );
        CHECK( BB_( 10100100 ) == 0xA4 );
        CHECK( BB_( 10100101 ) == 0xA5 );
        CHECK( BB_( 10100110 ) == 0xA6 );
        CHECK( BB_( 10100111 ) == 0xA7 );
        CHECK( BB_( 10101000 ) == 0xA8 );
        CHECK( BB_( 10101001 ) == 0xA9 );
        CHECK( BB_( 10101010 ) == 0xAA );
        CHECK( BB_( 10101011 ) == 0xAB );
        CHECK( BB_( 10101100 ) == 0xAC );
        CHECK( BB_( 10101101 ) == 0xAD );
        CHECK( BB_( 10101110 ) == 0xAE );
        CHECK( BB_( 10101111 ) == 0xAF );

        CHECK( BB_( 10110000 ) == 0xB0 );
        CHECK( BB_( 10110001 ) == 0xB1 );
        CHECK( BB_( 10110010 ) == 0xB2 );
        CHECK( BB_( 10110011 ) == 0xB3 );
        CHECK( BB_( 10110100 ) == 0xB4 );
        CHECK( BB_( 10110101 ) == 0xB5 );
        CHECK( BB_( 10110110 ) == 0xB6 );
        CHECK( BB_( 10110111 ) == 0xB7 );
        CHECK( BB_( 10111000 ) == 0xB8 );
        CHECK( BB_( 10111001 ) == 0xB9 );
        CHECK( BB_( 10111010 ) == 0xBA );
        CHECK( BB_( 10111011 ) == 0xBB );
        CHECK( BB_( 10111100 ) == 0xBC );
        CHECK( BB_( 10111101 ) == 0xBD );
        CHECK( BB_( 10111110 ) == 0xBE );
        CHECK( BB_( 10111111 ) == 0xBF );

        CHECK( BB_( 11000000 ) == 0xC0 );
        CHECK( BB_( 11000001 ) == 0xC1 );
        CHECK( BB_( 11000010 ) == 0xC2 );
        CHECK( BB_( 11000011 ) == 0xC3 );
        CHECK( BB_( 11000100 ) == 0xC4 );
        CHECK( BB_( 11000101 ) == 0xC5 );
        CHECK( BB_( 11000110 ) == 0xC6 );
        CHECK( BB_( 11000111 ) == 0xC7 );
        CHECK( BB_( 11001000 ) == 0xC8 );
        CHECK( BB_( 11001001 ) == 0xC9 );
        CHECK( BB_( 11001010 ) == 0xCA );
        CHECK( BB_( 11001011 ) == 0xCB );
        CHECK( BB_( 11001100 ) == 0xCC );
        CHECK( BB_( 11001101 ) == 0xCD );
        CHECK( BB_( 11001110 ) == 0xCE );
        CHECK( BB_( 11001111 ) == 0xCF );

        CHECK( BB_( 11010000 ) == 0xD0 );
        CHECK( BB_( 11010001 ) == 0xD1 );
        CHECK( BB_( 11010010 ) == 0xD2 );
        CHECK( BB_( 11010011 ) == 0xD3 );
        CHECK( BB_( 11010100 ) == 0xD4 );
        CHECK( BB_( 11010101 ) == 0xD5 );
        CHECK( BB_( 11010110 ) == 0xD6 );
        CHECK( BB_( 11010111 ) == 0xD7 );
        CHECK( BB_( 11011000 ) == 0xD8 );
        CHECK( BB_( 11011001 ) == 0xD9 );
        CHECK( BB_( 11011010 ) == 0xDA );
        CHECK( BB_( 11011011 ) == 0xDB );
        CHECK( BB_( 11011100 ) == 0xDC );
        CHECK( BB_( 11011101 ) == 0xDD );
        CHECK( BB_( 11011110 ) == 0xDE );
        CHECK( BB_( 11011111 ) == 0xDF );

        CHECK( BB_( 11100000 ) == 0xE0 );
        CHECK( BB_( 11100001 ) == 0xE1 );
        CHECK( BB_( 11100010 ) == 0xE2 );
        CHECK( BB_( 11100011 ) == 0xE3 );
        CHECK( BB_( 11100100 ) == 0xE4 );
        CHECK( BB_( 11100101 ) == 0xE5 );
        CHECK( BB_( 11100110 ) == 0xE6 );
        CHECK( BB_( 11100111 ) == 0xE7 );
        CHECK( BB_( 11101000 ) == 0xE8 );
        CHECK( BB_( 11101001 ) == 0xE9 );
        CHECK( BB_( 11101010 ) == 0xEA );
        CHECK( BB_( 11101011 ) == 0xEB );
        CHECK( BB_( 11101100 ) == 0xEC );
        CHECK( BB_( 11101101 ) == 0xED );
        CHECK( BB_( 11101110 ) == 0xEE );
        CHECK( BB_( 11101111 ) == 0xEF );

        CHECK( BB_( 11110000 ) == 0xF0 );
        CHECK( BB_( 11110001 ) == 0xF1 );
        CHECK( BB_( 11110010 ) == 0xF2 );
        CHECK( BB_( 11110011 ) == 0xF3 );
        CHECK( BB_( 11110100 ) == 0xF4 );
        CHECK( BB_( 11110101 ) == 0xF5 );
        CHECK( BB_( 11110110 ) == 0xF6 );
        CHECK( BB_( 11110111 ) == 0xF7 );
        CHECK( BB_( 11111000 ) == 0xF8 );
        CHECK( BB_( 11111001 ) == 0xF9 );
        CHECK( BB_( 11111010 ) == 0xFA );
        CHECK( BB_( 11111011 ) == 0xFB );
        CHECK( BB_( 11111100 ) == 0xFC );
        CHECK( BB_( 11111101 ) == 0xFD );
        CHECK( BB_( 11111110 ) == 0xFE );
        CHECK( BB_( 11111111 ) == 0xFF );

        return 0;
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk