Есть ли способ, чтобы тип `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, и назовите его. Таким образом, предупреждения также исчезнут.

Ответ 6

Почему бы не

enum EEE {
    X1 = 1,
    x = 2 // pick more descriptive name, a'course
};

или

if ( size_t( t ) < x )