Как повторно использовать перегрузки операторов перечисления в C ++? - PullRequest
1 голос
/ 22 июня 2010

У меня есть несколько флаговых перечислений в C ++. Например:

enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};
some_state var1;

Теперь при использовании битовых операторов, таких как & или |, я получаю ошибки компилятора. Я знаю, что могу перегрузить operator | эт.ал. для перечислений, но я ненавижу делать это снова для каждого перечисления. Есть ли хороший способ повторно использовать перегрузки оператора?

Ответы [ 3 ]

5 голосов
/ 22 июня 2010
enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};

int main() {
    some_state var1 = state_normal;
    some_state var2 = state_special;
    unsigned int var3 = var1 | var2;
}

У меня отлично работает. Причина, по которой вы не можете использовать |, & etc без перегрузки, заключается в том, что компилятор не может гарантировать результат var1 | var2 является допустимым значением в перечислении. Если вы хотите использовать сдвинутые флаги, вам нужно взять целочисленный тип, а не тип enum. Это постоянно используется в профессиональных заголовках, таких как Direct3D.

3 голосов
/ 22 июня 2010

Я пытался и искал, и я думаю, что лучшее решение - #define. На основании что-то, что я нашел :

#define FLAGS(T) \
inline T  operator  |(const T s, const T e) { return (T)((unsigned)s | e); } \
inline T &operator |=(T      &s, const T e) { return s = s | e; }            \
inline T  operator  &(const T s, const T e) { return (T)((unsigned)s & e); } \
inline T &operator &=(T      &s, const T e) { return s = s & e; }            \
inline T  operator  ^(const T s, const T e) { return (T)((unsigned)s ^ e); } \
inline T &operator ^=(T      &s, const T e) { return s = s ^ e; }            \
inline T  operator  ~(const T s)            { return (T)~(unsigned)s; }

Это можно использовать как:

enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};
FLAGS(some_state)

some_state var1;

Для Visual Studio это может понадобиться, чтобы отключить некоторые предупреждения:

#pragma warning(disable: 4505) // '*' : unreferenced local function has been removed

Фактически, Windows SDK имеет макрос DEFINE_ENUM_FLAG_OPERATORS , чтобы сделать это.


Другой подход - это класс-оболочка , например DEF_ENUM_FLAGS_TYPE использует .

Или используйте что-то вроде макроса LLVM_MARK_AS_BITMASK_ENUM . Возможно, вам понадобится недавний компилятор.

2 голосов
/ 22 июня 2010

Используйте существующую библиотеку шаблонов, такую ​​как bitwise-enum , чтобы предоставлять операции вместо того, чтобы писать свои собственные.

...