Есть ли способ сделать тип enum неподписанным? - PullRequest
10 голосов
/ 28 апреля 2010

Есть ли способ сделать тип 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 C ++ в соответствии со стандартом. Кажется, ошибка в VS. Спасибо Джеймсу за подсказку.

Ответы [ 6 ]

8 голосов
/ 28 апреля 2010

Вы можете попробовать:

enum EEE {
    X1 = 1,
    XN = -1ULL
};

Без U целочисленный литерал подписывается.

(Это, конечно, предполагает, что ваша реализация поддерживает long long; я предполагаю, что это так, поскольку в исходном вопросе используется LL; в противном случае вы можете использовать UL для long).

2 голосов
/ 28 апреля 2010

Вы также можете перегрузить операторов, если хотите сравнить

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

2 голосов
/ 28 апреля 2010

Не в текущей версии C ++. C ++ 0x будет предоставлять строго типизированные перечисления.

В настоящее время вы можете использовать if ( static_cast<size_t>(t) < x ) для удаления предупреждения.

1 голос
/ 24 ноября 2010
1 голос
/ 28 апреля 2010

Согласно Являются ли перечисления C ++ подписанными или беззнаковыми? ваш компилятор может выбрать, является ли enum подписанным или нет, хотя есть некоторые комментарии о том, что в C ++ 0x вы сможете указать, что он не подписан.

0 голосов
/ 28 апреля 2010

Почему бы не

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

или

if ( size_t( t ) < x )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...