Reputation: 1000
I have:
enum class orientation {
North,
East,
South,
West
};
I want to rotate its instance left (North => West) and right (West => North).
But I don't want to convert them to numbers, because it harms readability and intention and also jumping from the last number to first and back is strange.
I came up with lots of solutions, but all are kind of lame :(
Upvotes: 7
Views: 591
Reputation: 60238
Here's a solution that doesn't do any casting, and is quite easy to read:
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);
}
}
The major advantage to this solution is that it's robust to someone coming along and changing the order of the members in the enum class.
Upvotes: 3
Reputation: 16680
Make a class called Orientation
(say). Give it a member variable of the enumeration (orientation
). Define a getter/setter, and increment and decrement operators (or rotate_left
and rotate_right
if you like those names better). Make this all implementation details inside the class.
You can use the logic that Barry suggested; but bury it in the class where no one has to deal with it.
Upvotes: 1
Reputation: 303367
Since they're in order:
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};
}
Which you can check:
static_assert(rotate(orientation::North, 1) == orientation::East);
static_assert(rotate(orientation::North, -1) == orientation::West);
I picked the integer to mean "number of 90 degree turns right" but you can adjust as suitable for your actual problem. Or add helper functions like:
constexpr auto rotate_left(orientation o) -> orientation {
return rotate(o, -1);
}
constexpr auto rotate_right(orientation o) -> orientation {
return rotate(o, 1);
}
Upvotes: 9