Есть ли способ, чтобы тип `enum` был неподписанным?
Есть ли способ сделать тип enum
неподписанным? Следующий код дает мне предупреждение о сравнении с подписью/без знака.
enum EEE {
X1 = 1
};
int main()
{
size_t x = 2;
EEE t = X1;
if ( t < x ) std::cout << "ok" << std::endl;
return 0;
}
Я попытался заставить компилятор использовать неподписанный базовый тип для перечисления со следующим:
enum EEE {
X1 = 1,
XN = 18446744073709551615LL
// I've tried XN = UINT_MAX (in Visual Studio). Same warning.
};
Но это все еще дает предупреждение.
Изменение константы на UINT_MAX
заставляет ее работать в GNU С++, как это должно быть в соответствии со стандартом. Кажется, это ошибка в VS. Спасибо Джеймсу за подсказку.
Ответы
Ответ 1
Вы можете попробовать:
enum EEE {
X1 = 1,
XN = -1ULL
};
Без U
целочисленный литерал подписан.
(Это, конечно, предполагает, что ваша реализация поддерживает long long
; я предполагаю, что это происходит, поскольку исходный вопрос использует LL
, в противном случае вы можете использовать UL
для long
).
Ответ 2
Не в текущей версии С++. С++ 0x предоставит строго типизированные перечисления.
В настоящее время вы можете использовать if ( static_cast<size_t>(t) < x )
, чтобы удалить предупреждение.
Ответ 3
Вы также можете перегрузить операторы, если хотите сравнить их
enum EEE {
X1 = 1
};
bool operator<(EEE e, std::size_t u) {
return (int)e < (int)u;
}
Однако вы должны сделать этот танец для любого целочисленного типа с правой стороны. В противном случае, если вы сделаете e < 2
, это будет неоднозначно: компилятор может использовать ваш operator<
, соответствующий левой стороне, точно, но нуждающийся в преобразовании с правой стороны или его встроенном операторе, нуждающемся в продвижении по левой стороне и соответствующем ровная сторона точно.
Итак, в конечном итоге, я бы поставил следующие версии:
/* everything "shorter" than "int" uses either int or unsigned */
bool operator<(EEE e, int u) {
return (int)e < (int)u;
}
bool operator<(EEE e, unsigned u) {
return (unsigned int)e < (unsigned int)u;
}
bool operator<(EEE e, long u) {
return (long)e < (long)u;
}
bool operator<(EEE e, unsigned long u) {
return (unsigned long)e < (unsigned long)u;
}
/* long long if your compiler has it, too */
Не очень приятно:) Но, по крайней мере, пользователь вашего перечисления легко перемещается. Однако, если вы в конечном счете не хотите сравнивать с обычным int
, но против какой-либо значимой ценности, я бы сделал то, что предложил какой-то другой парень, и добавил еще один счетчик, который имеет значение 2
, и назовите его. Таким образом, предупреждения также исчезнут.
Ответ 4
В соответствии с Являются ли подписанные С++ или неподписанными?
ваш компилятор выбирает, подписано ли перечисление или нет, хотя есть некоторые комментарии, говорящие о том, что в С++ 0x вы сможете указать, что он неподписан.
Ответ 5
Per Декларации перечисления С++ в MSDN:
enum EEE : unsigned {
X1 = 1
};
Ответ 6
Почему бы не
enum EEE {
X1 = 1,
x = 2 // pick more descriptive name, a'course
};
или
if ( size_t( t ) < x )