Отзыв о переборе типов-безопасных перечислений - PullRequest
0 голосов
/ 31 мая 2010

В ответ на предыдущий вопрос SO " Enumerate over enum в C ++ " я предложил следующее многократно используемое решение, которое использует type-safe enum idiom . Мне просто любопытно увидеть отзывы сообщества о моем решении. В этом решении используется статический массив, который перед первым использованием заполняется с помощью безопасных типов перечислимых объектов. Итерация по перечислениям тогда просто сводится к итерации по массиву. Мне известно о том, что это решение не будет работать, если счетчики не увеличиваются строго.

template<typename def, typename inner = typename def::type>
class safe_enum : public def
{
  typedef typename def::type type;
  inner val;

  static safe_enum array[def::end - def::begin];
  static bool init;

  static void initialize()
  {
    if(!init) // use double checked locking in case of multi-threading.
    {
      unsigned int size = def::end - def::begin;
      for(unsigned int i = 0, j = def::begin; i < size; ++i, ++j)
        array[i] = static_cast<typename def::type>(j);
      init = true;
    }
  }

public:

  safe_enum(type v = def::begin) : val(v) {}
  inner underlying() const { return val; }

  static safe_enum * begin()
  {
    initialize();
    return array;
  }

  static safe_enum * end()
  {
    initialize();
    return array + (def::end - def::begin);
  }

  bool operator == (const safe_enum & s) const { return this->val == s.val; }
  bool operator != (const safe_enum & s) const { return this->val != s.val; }
  bool operator <  (const safe_enum & s) const { return this->val <  s.val; }
  bool operator <= (const safe_enum & s) const { return this->val <= s.val; }
  bool operator >  (const safe_enum & s) const { return this->val >  s.val; }
  bool operator >= (const safe_enum & s) const { return this->val >= s.val; }
};

template <typename def, typename inner>
safe_enum<def, inner> safe_enum<def, inner>::array[def::end - def::begin];

template <typename def, typename inner>
bool safe_enum<def, inner>::init = false;

struct color_def
{
  enum type
  {
      begin, red = begin, green, blue, end
  };
};

typedef safe_enum<color_def> color;

template <class Enum>
void f(Enum e)
{
  std::cout << static_cast<unsigned>(e.underlying()) << std::endl;
}

int main()
{
  std::for_each(color::begin(), color::end(), &f<color>);
  color c = color::red;
}

1 Ответ

0 голосов
/ 31 мая 2010

Я не смотрел остальную часть кода, но «двойная проверка блокировки» не работает - что, если два потока проверяют флаг одновременно, пока он все еще ложен? Вам нужно использовать реальную блокировку, если вы хотите поддерживать многопоточность.

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