Аккуратный способ, как циклически итерировать 4 значения класса enum в обоих направлениях в C ++? - PullRequest
7 голосов
/ 22 апреля 2020

У меня есть:

enum class orientation {
  North,
  East,
  South,
  West
};

Я хочу повернуть его экземпляр влево (север => запад) и вправо (запад => север).
Но я не хочу преобразовывать их в числа, потому что это вредит читабельности и намерению, а также перепрыгивание с последнего номера на первое и обратно странно.

Я придумал множество решений, но все они отстали: (

Ответы [ 3 ]

9 голосов
/ 22 апреля 2020

Так как они в порядке:

constexpr auto rotate(orientation o, int n) -> orientation {
    // convert to int
    int dir = (int)o;
    // rotate as an int
    dir = (dir + n) % 4;
    // account for negatives
    if (dir < 0) {
        dir += 4;
    }
    // and then convert back
    return orientation{dir};
}

Что вы можете проверить:

static_assert(rotate(orientation::North, 1) == orientation::East);
static_assert(rotate(orientation::North, -1) == orientation::West);

Я выбрал целое число для обозначения «число поворотов на 90 градусов вправо», но вы можете отрегулируйте как подходит для вашей актуальной проблемы. Или добавьте вспомогательные функции, такие как:

constexpr auto rotate_left(orientation o) -> orientation {
    return rotate(o, -1);
}

constexpr auto rotate_right(orientation o) -> orientation {
    return rotate(o, 1);
}
3 голосов
/ 23 апреля 2020

Вот решение, которое не выполняет кастинг, и его довольно легко прочитать:

constexpr auto rotate(orientation o, int n) -> orientation
{
  n = (n + 4) % 4; // for negative rotations  
  if (!n) 
    return o;
  switch (o)
  {
    case orientation::North : return rotate(orientation::East, n - 1);
    case orientation::East  : return rotate(orientation::South, n - 1);
    case orientation::South : return rotate(orientation::West, n - 1);
    case orientation::West  : return rotate(orientation::North, n - 1);
  }
}

Основным преимуществом этого решения является то, что оно надежно для того, чтобы кто-то пришел и изменил порядок члены в классе enum.

1 голос
/ 22 апреля 2020

Создайте класс с именем Orientation (скажем). Дайте ему переменную-член перечисления (orientation). Определите метод получения / установки, а также операторы увеличения и уменьшения (или rotate_left и rotate_right, если вам больше нравятся эти имена). Сделайте все детали реализации внутри класса.

Вы можете использовать logi c, который предложил Барри; но похороните его в классе, где никто не должен иметь с этим дело.

...