Как проверить, соответствует ли константа типу во время компиляции? - PullRequest
3 голосов
/ 03 сентября 2010

Я хотел бы добавить утверждения времени компиляции в следующий код C ++ (скомпилированный с Visual C ++ 9):

//assumes typedef unsigned char BYTE;
int value = ...;
// Does it fit into BYTE?
if( 0 <= value && value <= UCHAR_MAX ) {
    BYTE asByte = static_cast<BYTE>( value );
    //proceed with byte
} else {
    //proceed with greater values
}

Проблема в UCHAR_MAX и BYTE независимы typedef си когда этот код портирован, может случиться так, что они выйдут из синхронизации и код сломается.Итак, я хотел сделать что-то вроде этого:

compileTimeAssert( sizeof( BYTE ) == sizeof( UCHAR_MAX ) );

, но VC ++ 9 выдает ошибку "отрицательный индекс" при компиляции, что sizeof( UCHAR_MAX ) оказывается 4, а не 1.

Как мне выполнить проверку во время компиляции, которую я хочу?

Ответы [ 5 ]

5 голосов
/ 03 сентября 2010

сравнить 'значение' с std :: numeric_limits :: max () вместо UCHAR_MAX

2 голосов
/ 03 сентября 2010

Вы можете проверить во время компиляции, что ( (1 << (sizeof(BYTE)*CHAR_BIT)) - 1 ) == UCHAR_MAX.

(я предполагаю, что вы не спрашиваете, как сделать статическое утверждение - есть несколько способов, см. здесь )

1 голос
/ 03 сентября 2010

UCHAR_MAX - максимальное значение unsigned char.Размер unsigned char всегда равен 1 байту.Если вы хотите проверить, является ли диапазон BYTE 0 .. UCHAR_MAX или -(UCHAR_MAX/2+1) .. UCHAR_MAX/2, тогда просто проверьте, если sizeof(BYTE) == 1

Если вы хотите проверить, если некоторые intзначение вписывается в BYTE, затем выполните:

if (!(value & ~(BYTE)-1)) ...
1 голос
/ 03 сентября 2010

но VC ++ 9 выдает "негатив подпись "ошибка при компиляции - sizeof (UCHAR_MAX) равен 4, а не 1.

В этом посте я не отвечаю с точки зрения решения, но пытаюсь найти причину.

Рассмотрим выражение

#define MAX 255;

Насколько я понимаю, sizeof(MAX) a.k.a (sizeof(255)) всегда будет иметь размер целочисленного литерала на данной платформе в соответствии с данными правилами в стандарте 2.3.1 / 2. То, что это UCHAR_MAX и содержит максимальное значение char, не означает, что размер такого имени будет равен char

Тип целочисленного литерала зависит по форме, значению и суффиксу. Если оно является десятичным и не имеет суффикса, имеет первый из этих типов, в котором его значение может быть представлено: int, long INT; если значение не может быть представлен как длинный int, поведение не определено. Если это восьмеричное или шестнадцатеричный и не имеет суффикса, это имеет первый из этих типов, в котором его значение может быть представлено: int, unsigned int, long int, unsigned long внутр. Если это суффикс U или U, его тип является первым из этих типов в какое его значение можно представить: unsigned int, unsigned long int. Если оно с суффиксом l или L, его тип первый из этих типов, в котором его значение может быть представлено: long int, без знака длинный инт. Если это суффикс по ul, lu, uL, Lu, Ul, lU, UL или LU, его тип - беззнаковое длинное целое.

Таким образом, ожидание того, что оно будет 1, необходимо перепроверить, что, по-видимому, является коренной причиной здесь. sizeof(MAX) будет одним только на тех архитектурах, где int такой же ширины, как char. Я не уверен, сколько таких систем действительно существует.

1 голос
/ 03 сентября 2010

Использовать BOOST_STATIC_ASSERT .

...