C ++ - 反转枚举值

时间:2014-09-01 01:22:55

标签: c++ enums invert

我有一个这样的枚举:

enum class ShootingDirection
{
    Down,
    Up,
    Right,
    Left
};

我还声明了那种类型的类成员需要在某种方法中被反转,无论何时何地都无关紧要。倒置我的意思是Down - >向上(反之亦然)和向右 - >左(再次,反过来)。 而不是切换或一堆if ... else ifs我使用了这样声明的地图:

std::map<ShootingDirection, ShootingDirection> _invertedDirectionsMap;

它充满了这样的数据:

_invertedDirectionsMap[ShootingDirection::Down] = ShootingDirection::Up;
_invertedDirectionsMap[ShootingDirection::Up] = ShootingDirection::Down;
_invertedDirectionsMap[ShootingDirection::Right] = ShootingDirection::Left;
_invertedDirectionsMap[ShootingDirection::Left] = ShootingDirection::Right;

其类型为ShootingDirection的变量的反转非常简单(假设它已初始化):

_direction = _invertedDirectionsMap[_direction];

我认为这是对地图的愚蠢使用和不必要的开销。有更聪明的方法吗? 那么这个问题是否属于Code Review或者这里?我对这个标准并不熟悉。

6 个答案:

答案 0 :(得分:4)

我通常在一个圆圈中布置方向枚举(基本上与从x轴测量角度的方式相匹配。所以:

enum ShootingDirection { Right, Down, Left, Up };

匹配0度,90度,180度,270度。这对我来说是一个直观的布局。

然后倒置的方向就是:(dir + 2) % 4。或者更全面:

int InvertDirection(int dir)
{
    return (dir + 2) % 4;
}

我喜欢这个,因为我发现使用它非常直观。顺时针转弯为(dir + 1) % 4,逆时针转动(dir + 3) % 4

它也可以轻松扩展到更多方向。我将它用于六边形方向:现在是倒置的方向(dir + 3) % 6

答案 1 :(得分:2)

是:改为使用switch声明。它将大大提高效率。如果这还不够好,请考虑一下:

enum class ShootingDirection
{
    Down = 1,
    Up = -1,
    Right = 2,
    Left = -2
};

然后你可以通过算术否定反转(并且当然可以转换为int)。

答案 2 :(得分:2)

其他人已经开始暗示这个解决方案了,但这很快,并且避免了你说你不想要的转换声明:

enum ShootingDirection {
    Down = -2,
    Up = 2,
    Right = 1,
    Left = -1
};

inline ShootingDirection invert(ShootingDirection d) {
    return static_cast<ShootingDirection>(-static_cast<int>(d));
}

理想情况下,这应该内联到只有一个汇编指令。

答案 3 :(得分:1)

enum class Direction {
    UP = 1,
    DOWN = 2,
    LEFT = 3,
    RIGHT = 4
};

enum class InvertedDirection {
    UP = 2,
    DOWN = 1,
    LEFT = 4,
    RIGHT = 3
};

InvertedDirection getInvertedDirection(Direction dir) {
    return static_cast<InvertedDirection>(dir);
}

这是你得到的最快的。使用静态转换然后交换反转值你实际上不会比这更快。

该功能实际上只是一个帮手,你可以随心所欲地进行静态演员。无论哪种方式,这都会阻止编译器发出任何转换代码。

答案 4 :(得分:1)

你问:

  

有更聪明的方法吗?

这是另一种扭转方向的方法:

#include <iostream>

enum class ShootingDirection : unsigned char
{
   Up    = 0x00,
   Down  = 0xFF,
   Left  = 0x01,
   Right = 0xFE
};

ShootingDirection reverseDirection(ShootingDirection dir)
{
   return ShootingDirection((unsigned char)dir ^ 0xFF);
}

int main()
{
   ShootingDirection up = ShootingDirection::Up;
   ShootingDirection down = ShootingDirection::Down;
   ShootingDirection left = ShootingDirection::Left;
   ShootingDirection right = ShootingDirection::Right;

   std::cout << "Up: " << (int)up << ", Reverse: " << (int)reverseDirection(up) << std::endl;
   std::cout << "Down: " << (int)down << ", Reverse: " << (int)reverseDirection(down) << std::endl;
   std::cout << "Left: " << (int)left << ", Reverse: " << (int)reverseDirection(left) << std::endl;
   std::cout << "Right: " << (int)right << ", Reverse: " << (int)reverseDirection(right) << std::endl;

   return 0;
}

输出:

Up: 0, Reverse: 255
Down: 255, Reverse: 0
Left: 1, Reverse: 254
Right: 254, Reverse: 1

答案 5 :(得分:1)

没有分支就可以做到这一点。

http://coliru.stacked-crooked.com/a/4b0a1e3c58b74004

诀窍是:

/* The direction type is 8 bits, only the first 2 are used */
/* The first 2 bits have the following meanings */
typedef unsigned char direction;
const direction down  = '\x00'; /* 00000000 */
const direction up    = '\x03'; /* 00000011 */
const direction left  = '\x01'; /* 00000001 */
const direction right = '\x02'; /* 00000010 */
/* All other values are interpreted by first zeroing out the last 6 bits */

/* Use to zero out all bits but the last two, also for XORing */
static const direction oneone = '\x03';

inline direction xorflip(const direction d)
{
    /*
     * XOR with 11
     * 00 ^ 11 = 11, down  to up
     * 01 ^ 11 = 10, left  to right
     * 10 ^ 11 = 01, right to left
     * 11 ^ 11 = 00, up    to down
     */
    return d ^ oneone;
}