Макрос C, вычисляющий количество байтов, которое требует данная константа времени компиляции - PullRequest
2 голосов
/ 10 октября 2010

Часто у меня есть некоторое постоянное число времени компиляции, которое также является верхним пределом возможных значений, принимаемых переменными.И поэтому я заинтересован в выборе наименьшего типа, который может вместить эти значения.Например, я могу знать, что переменные будут вписываться в диапазон <-30 000, 30 000>, поэтому при поиске подходящего типа я бы начал со знака short int.Но так как я переключаюсь между платформами и компиляторами, мне бы хотелось, чтобы во время компиляции проверялась, действительно ли верхние значения констант действительно соответствуют этому типу.BOOST_STATIC_ASSERT (sizeof (T)> = required_number_of_bytes_for_number) работает нормально, но проблема в следующем: как автоматически определить количество байтов, необходимое для хранения заданной постоянной времени компиляции, со знаком или без знака?Я думаю, макрос C мог бы сделать эту работу?Кто-нибудь может написать это для меня?Я мог бы использовать std :: numeric_limits :: max () и min () вместо вычисления байтов, но тогда мне пришлось бы переключиться на assert во время выполнения: (

Ответы [ 4 ]

4 голосов
/ 10 октября 2010

Теперь, когда это помечено c ++, я предлагаю использовать Boost.Integer для выбора подходящего типа. boost::int_max_value_t< MyConstant >::least даст тип, который вы ищете.

0 голосов
/ 11 октября 2010

Как насчет BOOST_STATIC_ASSERT(int(60000)==60000)?Это проверит, подходит ли 60000 в int.Если int равен 16 битам, int(60000) равен 27232.Для сравнения это будет затем расширено до нуля до 32 бит и надежно завершится неудачей.

0 голосов
/ 10 октября 2010

Вы можете использовать следующий код. Это работает только для положительных 8/16/32/64-битных целых чисел. Но вы можете внести соответствующие изменения и для отрицательных значений.

template <typename T, T x> class TypeFor
{
    template <T x>
    struct BitsRequired {
        static const size_t Value = 1 + BitsRequired<x/2>::Value;
    };
    template <>
    struct BitsRequired<0> {
        static const size_t Value = 0;
    };


    static const size_t Bits = BitsRequired<x>::Value;
    static const size_t Bytes = (Bits + 7) / 8;

    static const size_t Complexity = 1 + BitsRequired<Bytes-1>::Value;

    template <size_t c> struct Internal {
    };

    template <> struct Internal<1> {
        typedef UCHAR Type;
    };
    template <> struct Internal<2> {
        typedef USHORT Type;
    };
    template <> struct Internal<3> {
        typedef ULONG Type;
    };
    template <> struct Internal<4> {
        typedef ULONGLONG Type;
    };

public:

    typedef typename Internal<Complexity>::Type Type;

};


TypeFor<UINT, 117>::Type x;

P.S. это компилируется под MSVC. Вероятно, необходимо внести некоторые изменения, чтобы принять его для gcc / mingw / etc.

0 голосов
/ 10 октября 2010

Как насчет того, чтобы избежать проблемы:

BOOST_STATIC_ASSERT((1LL << (8*sizeof(T))) >= number);
...